# PWA Storefront Pack

> Guia completo de instalação, configuração e utilização do PWA Storefront Pack: o plugin que transforma a sua loja WooCommerce numa Progressive Web App instalável, com modo offline e notificações push…

- Página: <https://www.datafirefly.com/pt/documentation/pwa-storefront-pack/>
- Idioma: pt
- Atualizado em: 2026-10-10
- Outros idiomas: [fr](https://www.datafirefly.com/documentation/pwa-storefront-pack/index.md), [en](https://www.datafirefly.com/en/documentation/pwa-storefront-pack/index.md), [es](https://www.datafirefly.com/es/documentation/pwa-storefront-pack/index.md), [de](https://www.datafirefly.com/de/documentation/pwa-storefront-pack/index.md), [it](https://www.datafirefly.com/it/documentation/pwa-storefront-pack/index.md), [pl](https://www.datafirefly.com/pl/documentation/pwa-storefront-pack/index.md), [nl](https://www.datafirefly.com/nl/documentation/pwa-storefront-pack/index.md)
- Índice: <https://www.datafirefly.com/pt/documentation/llms.txt>

Guia completo de instalação, configuração e utilização do **PWA Storefront Pack**: o plugin que transforma a sua loja WooCommerce numa Progressive Web App instalável, com modo offline e notificações push VAPID nativas (sem Firebase, sem OneSignal e sem subscrição mensal).

## Visão geral e princípio de funcionamento

O PWA Storefront Pack acrescenta ao seu WooCommerce três blocos independentes mas complementares:

- **Web App Manifest**: os seus clientes podem instalar a loja no ecrã principal como uma verdadeira aplicação (ícone, ecrã de arranque, modo standalone sem barra de endereço).
- **Service Worker**: cache inteligente das páginas e dos recursos, página offline personalizável, exclusões automáticas das zonas sensíveis (carrinho, checkout, a minha conta).
- **Notificações push VAPID**: implementação completa do protocolo Web Push em PHP puro: ECDSA P-256, JWT ES256 e cifragem aes128gcm. O seu servidor dialoga diretamente com os serviços push dos navegadores.

**Sem serviços de terceiros.** Ao contrário da maioria das soluções push para WordPress, nenhum dado de cliente passa por um intermediário. As suas chaves VAPID são geradas e guardadas no seu servidor. Fala diretamente com o FCM (Google), o Mozilla autopush, o WNS (Microsoft), etc.

## Requisitos

- WordPress 6.2 ou superior
- WooCommerce 7.0 ou superior
- PHP 7.4 ou superior com a extensão `openssl` (ativa por predefinição em todos os alojamentos)
- **HTTPS obrigatório**: os navegadores recusam registar um Service Worker ou gerir notificações push em HTTP (exceto em localhost, para desenvolvimento)

Se o seu site ainda não estiver em HTTPS, ative-o antes de instalar o plugin. Todas as funcionalidades PWA serão desativadas silenciosamente em HTTP.

## Instalação

1. Descarregue o arquivo `pwa-storefront-pack.zip` a partir da sua conta DataFirefly.
2. No WordPress, vá a **Plugins → Adicionar → Carregar plugin**.
3. Selecione o ZIP e clique em **Instalar agora** e depois em **Ativar**.
4. Na ativação, o plugin cria três tabelas SQL (`wp_pwasp_subscriptions`, `wp_pwasp_push_log`, `wp_pwasp_stock_waitlist`) e gera automaticamente o seu par de chaves VAPID.
5. Vá a **WooCommerce → PWA Storefront** para configurar.

## Configuração geral

O separador **General** centraliza a identidade da sua aplicação:

- **Enable PWA**: interruptor principal. Desative para retirar temporariamente o manifesto e o Service Worker sem desinstalar o plugin.
- **App name**: nome completo apresentado na instalação e no ecrã de arranque (por exemplo «A Minha Loja Oficial»).
- **Short name**: texto curto por baixo do ícone do ecrã principal, limitado a 12 carateres por convenção Android.
- **Theme color**: cor da barra de endereço e do seletor de tarefas (recomendado: a cor principal da sua marca).
- **Background color**: fundo do ecrã de arranque durante o carregamento da app (muitas vezes branco ou muito claro).

### URL dos endpoints

O plugin serve dois endpoints críticos:

- `https://o-seu-site.com/pwasp-manifest.json`: o Web App Manifest
- `https://o-seu-site.com/pwasp-service-worker.js`: o Service Worker

**Importante para os plugins de cache:** estes dois URL têm de ser sempre servidos frescos. Acrescente-os às exclusões do WP Rocket, do W3 Total Cache, do LiteSpeed Cache ou do seu CDN. Caso contrário, as atualizações de configuração nunca chegam aos navegadores.

## Manifesto

O separador **Manifest** controla o comportamento da app instalada:

- **Display mode**: `standalone` por predefinição (recomendado, experiência do tipo app). Outras opções: `fullscreen`, `minimal-ui`, `browser`.
- **Orientation**: `any`, `portrait` ou `landscape`. Em telemóvel, `portrait` costuma ser o mais adequado às lojas.
- **Start URL**: caminho onde a app abre no arranque. Por predefinição `/`. Pode apontar para `/shop` para abrir diretamente o catálogo.
- **Scope**: perímetro de URL controlado pela app. Geralmente `/`. Só o restrinja se usar a PWA apenas numa subpasta.
- **Categories**: indicações para as app stores web (Chrome, Edge). Exemplo: `shopping,business`.
- **Shortcuts**: ative para gerar atalhos de Loja / Carrinho / A minha conta acessíveis por pressão longa no ícone do ecrã principal.

## Ícones da aplicação

O separador **Icons** permite associar os seus ícones a partir da biblioteca de multimédia do WordPress. São suportados cinco formatos:

- **Ícone 192×192 (any purpose)**: obrigatório. Usado no Android e nos resultados do motor de pesquisa.
- **Ícone 512×512 (any purpose)**: obrigatório. Ícone do ecrã de arranque.
- **Maskable 192×192**: opcional. Com margem de segurança interna de 10% para os ícones adaptativos do Android (formas redondas, quadradas, em gota).
- **Maskable 512×512**: opcional. Mesmo princípio para o ecrã de arranque.
- **Apple Touch Icon 180×180**: para iOS. Sem cantos arredondados (o iOS acrescenta-os automaticamente).

**Dica sobre ícones maskable:** use uma ferramenta como o `maskable.app` para gerar as suas variantes maskable com a safe zone certa. Um logótipo sem margem de segurança fica cortado em alguns telemóveis Android.

Enquanto não houver ícone configurado, o plugin usa os ícones predefinidos fornecidos (marca DataFirefly). Substitua-os antes de passar a produção.

## Modo offline e estratégia de cache

O separador **Offline & Cache** configura o comportamento do Service Worker:

### Estratégias

- **Network first** (recomendado): o navegador tenta a rede e depois recorre à cache se estiver offline. Frescura máxima dos preços e do stock.
- **Cache first**: a cache responde de imediato e a rede atualiza em segundo plano. Mais rápido, mas pode apresentar preços ligeiramente desatualizados.

As estratégias aplicam-se apenas às **páginas HTML**. Os outros tipos de recurso têm estratégias fixas ótimas:

- CSS / JS / tipos de letra → _cache-first_ (só mudam nas atualizações de versão)
- Imagens de produto → _stale-while-revalidate_ (apresentação imediata a partir da cache, atualização em segundo plano)

### Âmbito da cache

Três caixas de seleção permitem ativar ou desativar a cache por tipo:

- **Cache HTML pages**: páginas de produto, de categoria, página inicial, artigos
- **Cache CSS / JS / fonts**: o esqueleto do seu tema
- **Cache images**: visuais de produto, imagens dos artigos do blogue

**Sempre excluídos da cache** (seja qual for a configuração): `/wp-admin/`, `/wp-login.php`, `/cart`, `/checkout`, `/my-account` e todos os endpoints AJAX do WooCommerce. Estas zonas exigem um estado fresco e autenticado em permanência.

### Página offline

Duas opções:

- **Usar o ecrã predefinido**: ecrã minimalista integrado no plugin (ícone, mensagem, botão Tentar de novo), com as cores da sua marca.
- **Usar uma página personalizada**: selecione uma página WordPress existente. Fica pré-colocada em cache na instalação do Service Worker e é servida em caso de falha de rede.

## Banner de instalação

O separador **Install Banner** controla a promoção da instalação:

- **Delay (page views)**: número de páginas vistas antes da apresentação. 3 por predefinição: o utilizador manifestou um interesse mínimo sem ser importunado logo na primeira visita.
- **Banner title / text / CTA / Dismiss**: textos totalmente personalizáveis, traduzíveis através do `.pot`.

Comportamento:

- No **Chrome, Edge, Opera e Samsung Internet**: o banner aparece quando o navegador assinala que o site é instalável (`beforeinstallprompt`). Um clique no CTA abre a caixa nativa de instalação.
- No **Safari em iOS**: o banner apresenta automaticamente as instruções «Toque em Partilhar e depois em Adicionar ao ecrã principal» (a Apple não oferece uma API de instalação programática).
- **Recusa memorizada durante 7 dias**: se o utilizador fechar o banner, este não reaparece durante uma semana.
- **Deteção automática**: se a app já estiver instalada (modo standalone detetado), o banner deixa de aparecer.

## Notificações push: as chaves VAPID

As notificações push usam o protocolo **VAPID** (Voluntary Application Server Identification), padrão do W3C. Na ativação do plugin, é gerado automaticamente um par de chaves ECDSA P-256:

- **Chave pública**: partilhada com os navegadores dos subscritores (através de JavaScript). 65 bytes, codificada em base64url.
- **Chave privada**: nunca transmitida, serve para assinar cada envio. 32 bytes.

O separador **Push Notifications** mostra a sua chave pública em claro e o número de subscrições ativas. Pode copiá-la para eventuais testes externos.

### Regeração das chaves

O botão **Regenerate keys** gera um novo par. Esta operação é **destrutiva**:

Regerar as chaves invalida instantaneamente **todas as subscrições existentes**. O plugin esvazia automaticamente a tabela de subscrições depois da confirmação. Os navegadores dos subscritores continuam a receber as notificações já assinadas, mas qualquer nova notificação falha silenciosamente até o utilizador voltar a subscrever.

Só regenere as chaves em caso de comprometimento comprovado ou numa migração entre ambientes.

### VAPID subject

Campo **VAPID subject**: endereço de contacto no formato `mailto:voce@exemplo.com` ou `https://exemplo.com/contacto`. Alguns serviços push (nomeadamente o da Mozilla) usam-no para o contactar em caso de abuso detetado no seu servidor. Vem pré-preenchido com o e-mail de administração do WordPress.

## Pedido de adesão e RGPD

A secção **Opt-in prompt** configura o pré-convite apresentado antes da caixa de diálogo nativa de permissão:

- **Show opt-in prompt**: ativa o pré-convite personalizado. Recomendado: a caixa nativa isolada tem uma taxa de recusa elevada e bloqueia qualquer novo pedido durante 30 dias.
- **GDPR consent required**: nunca apresenta a caixa nativa sem um clique explícito do utilizador no seu CTA. Exigido na Europa para haver conformidade com o RGPD.
- **Delay (seconds)**: espera antes da apresentação. 10 segundos por predefinição: deixar o utilizador explorar antes de pedir a permissão.
- **Prompt title / text / CTA / Dismiss**: textos totalmente personalizáveis.

**Boas práticas:** explique o valor acrescentado para o utilizador («Acompanhe as suas encomendas em tempo real»), não para si («Fique a par das nossas ofertas»). A taxa de aceitação é 3 a 4 vezes superior.

## Acionadores automáticos

O plugin traz três automatizações ligadas diretamente aos hooks do WooCommerce. Cada uma pode ser ativada de forma independente.

### Estado da encomenda

Hook: `woocommerce_order_status_changed`.
O cliente identificado (não os convidados) recebe uma notificação a cada transição de estado da sua encomenda. Título: «Encomenda #1042 atualizada». Corpo: «Estado: Expedida». Clique → página de seguimento da encomenda.

A notificação usa uma `tag` única por encomenda (`order-1042`): as atualizações sucessivas substituem a anterior em vez de se acumularem.

### Nova encomenda (administração)

Hook: `woocommerce_new_order`.
Todos os utilizadores com o perfil _administrator_ ou _shop_manager_ e subscritos ao push recebem uma notificação a cada nova encomenda. Título: «Nova encomenda recebida». Corpo: «Encomenda #1042, 189,00 €». Clique → ecrã de edição da encomenda.

O URL de administração tem **consciência do HPOS**: se o seu WooCommerce usar o High-Performance Order Storage, a ligação aponta para o novo esquema (`admin.php?page=wc-orders`). Caso contrário, para o antigo (`post.php?post=X`).

### Regresso ao stock

Hooks: `woocommerce_product_set_stock` e `woocommerce_variation_set_stock`.
Quando um produto passa de «esgotado» a «em stock», o plugin envia uma notificação a todos os visitantes que se tinham inscrito na lista de espera. Título: «De volta ao stock!». Corpo: «Ténis de couro premium edição limitada está de novo disponível». Imagem do produto em pré-visualização, se existir.

Cada entrada é marcada com `notified_at` após o envio bem-sucedido, para evitar duplicados se o stock oscilar.

## Compositor de broadcast

Menu: **WooCommerce → PWA Broadcast**. Interface para enviar uma notificação manual a todos os subscritores ativos (campanhas de marketing, anúncios, etc.).

Campos:

- **Title**: título da notificação (recomenda-se um máximo de 100 carateres)
- **Message**: corpo da notificação (recomenda-se um máximo de 200 carateres)
- **Open URL**: página onde o utilizador chega ao clicar (por predefinição, a página inicial)
- **Image URL**: imagem grande apresentada na notificação (apenas no Android, o iOS não a apresenta)

Uma pré-visualização em tempo real mostra a apresentação aproximada da notificação à direita do ecrã.

Dois botões:

- **Send broadcast**: envio a todos os subscritores ativos (exige confirmação)
- **Send test to me**: envio apenas às suas próprias subscrições. Útil para validar a apresentação antes de um broadcast em massa.

**Momento do envio:** evite broadcasts a meio da noite. No Android, as notificações tocam por predefinição. Um envio às 21h de sexta-feira tem uma taxa de cliques 2 vezes superior a um envio às 3h da manhã.

## Lista de espera de regresso ao stock (API JavaScript)

Para permitir que os visitantes se inscrevam na lista de espera de um produto esgotado, chame a partir do seu tema:

```
window.PWASP.addToWaitlist(productId)
  .then(result => {
    if (result.success) {
      alert('Será notificado assim que o produto voltar ao stock!');
    }
  });
```

Comportamento:

1. Se o utilizador ainda não estiver subscrito ao push, abre-se a caixa nativa de permissão.
2. Assim que a subscrição fica registada no servidor, a entrada é acrescentada à lista de espera do produto.
3. Quando o regresso ao stock é detetado, é enviada automaticamente uma notificação push.

Pode chamar esta API a partir de qualquer botão personalizado ou do hook `woocommerce_single_product_summary` através de um mu-plugin.

### Outras API JS expostas

```
// Subscrever manualmente (por exemplo a partir de um botão personalizado)
window.PWASP.subscribePush();

// Cancelar a subscrição (botão «Cancelar subscrição»)
window.PWASP.unsubscribePush();
```

## API REST

O plugin expõe seis endpoints no namespace `pwasp/v1`:

- `POST /wp-json/pwasp/v1/subscribe`: regista uma subscrição. Corpo: objeto `PushSubscription` do navegador.
- `POST /wp-json/pwasp/v1/unsubscribe`: elimina uma subscrição. Corpo: `{ endpoint: "..." }`.
- `POST /wp-json/pwasp/v1/test`: envio de teste ao utilizador atual (exige autenticação, permissão `manage_woocommerce`).
- `POST /wp-json/pwasp/v1/broadcast`: difusão a todos os subscritores (exige autenticação).
- `POST /wp-json/pwasp/v1/regenerate-vapid`: regera as chaves VAPID (exige autenticação).
- `POST /wp-json/pwasp/v1/waitlist`: acrescenta a uma lista de espera. Corpo: `{ subscription_id, product_id }`.

Autenticação: nonce do WordPress `X-WP-Nonce` nos endpoints públicos, permissão `manage_woocommerce` nos endpoints de administração.

## Compatibilidade e casos particulares

### HPOS (High-Performance Order Storage)

O plugin declara formalmente a compatibilidade HPOS ao WooCommerce através do `FeaturesUtil::declare_compatibility`. Verá a caixa assinalada em **WooCommerce → Definições → Avançado → Funcionalidades**.

### Plugins de cache

Acrescente as seguintes exclusões no seu plugin de cache:

- `/pwasp-manifest.json`
- `/pwasp-service-worker.js`

Alguns plugins (WP Rocket, LiteSpeed) oferecem também uma opção para _não colocar em cache_ os ficheiros JavaScript assinados como Service Worker. Ative-a se estiver disponível.

### iOS e Safari

Suporte por versão:

- **iOS 16.4 e superior**: instalação através de «Adicionar ao ecrã principal» e notificações push (apenas nas PWA instaladas)
- **iOS 15 e 16.3**: instalação possível, notificações push indisponíveis
- **iOS 14 e inferior**: instalação possível, sem notificações

Em iOS, o push só funciona se o utilizador tiver primeiro instalado a PWA no ecrã principal. É uma imposição da Apple, não do plugin.

### Multilingue: WPML e Polylang

O plugin é compatível com o **WPML** (incluindo o WooCommerce Multilingual) e com o **Polylang / Polylang Pro**, em modo subdiretórios (`/en/`, `/it/`), subdomínios ou parâmetro de idioma:

- **Service Worker**: registado sempre a partir da raiz do site (`/pwasp-service-worker.js`) com um scope `/`, pelo que um único SW cobre todos os idiomas.
- **Manifesto**: servido em cada idioma (`/en/pwasp-manifest.json`) com nome, descrição e `start_url` desse idioma. O campo `id` é idêntico em todo o lado: a app instalada a partir de `/it/` e a partir de `/pt/` é a mesma app.
- **Textos de administração** (banner de instalação, pré-convite de push, mensagem offline, nome e nome curto da app): registados automaticamente em **WPML → String Translation** (domínio «PWA Storefront Pack») e em **Idiomas → Traduções de cadeias** no Polylang. Introduza-os no idioma predefinido e traduza-os aí.
- **Notificações push**: enviadas no idioma de cada subscritor (locale memorizada na inscrição). O alerta de regresso ao stock usa o nome e o URL do produto traduzido.
- **Ecrã offline**: pré-colocado em cache para cada idioma e servido no idioma da página pedida.
- **Carrinho / Encomenda / A minha conta**: excluídos da cache seja qual for a tradução do slug (resolvidos por idioma no servidor).

**WooCommerce Multilingual multimoeda:** como a moeda é selecionada por cookie, dois visitantes veem preços diferentes no mesmo URL. O plugin força por isso a estratégia HTML em _network-first_ e nunca coloca em cache os URL de mudança de moeda (`?currency=`). O montante das notificações de «nova encomenda» é sempre o da encomenda, na sua moeda.

### Subpastas e multisite

O plugin funciona com o WordPress instalado na raiz (`example.com`) ou numa subpasta (`example.com/shop/`). Os endpoints são resolvidos dinamicamente através do `home_url()`. Em multisite, ative o plugin site a site: cada site terá o seu próprio par de chaves VAPID e a sua própria base de subscritores.

## Resolução de problemas

### «O Service Worker não está registado»

1. Verifique que o seu site está mesmo em HTTPS (`https://` e não `http://`).
2. Abra a consola do navegador (F12 → separador Application → Service Workers). Existe alguma mensagem de erro?
3. Teste o URL `https://o-seu-site.com/pwasp-service-worker.js` num separador. O ficheiro tem de devolver JavaScript, não uma página 404 nem a página inicial do WordPress.
4. Se der 404: vá a **Definições → Permalinks** e clique em **Guardar alterações** para atualizar as regras de reescrita.

### «As notificações não chegam»

1. Verifique em **WooCommerce → PWA Subscribers** que a sua subscrição está listada e no estado _active_.
2. Use o botão **Send test to me** no compositor de broadcast. Recebe a notificação?
3. Se não: a caixa de permissão pode ter sido recusada. No Chrome: abra o cadeado na barra de endereço → Notificações → Permitir.
4. Em Windows/macOS: verifique que o Chrome ou o Firefox não estão em modo «Não incomodar».

### «A regeração das chaves VAPID falhou»

Causa provável: a extensão PHP `openssl` não está disponível no seu alojamento, ou a geração de chaves ECDSA está bloqueada. Verifique num ficheiro `phpinfo.php` que a secção `openssl` está presente e que a curva `prime256v1` é suportada. Contacte o seu alojamento se for necessário.

## Desinstalação

Remoção através de **Plugins → Plugins instalados → Eliminar**:

- As três tabelas SQL são eliminadas
- As opções do plugin são eliminadas
- As tarefas cron agendadas são canceladas
- Os ícones carregados para a biblioteca de multimédia **mantêm-se** (podem ser úteis noutro lado)

## Suporte

Para qualquer questão ou anomalia, abra um pedido a partir da sua [conta DataFirefly](https://www.datafirefly.com/pt/minha-conta/). Resposta em 24 horas úteis.
