PWA Storefront Pack
Installation, manifest and Service Worker configuration, VAPID key management, automated triggers and broadcasts.
Complete guide to installing, configuring and using PWA Storefront Pack: the plugin that turns your WooCommerce store into an installable Progressive Web App with offline mode and native VAPID push notifications (no Firebase, no OneSignal, no monthly subscription).
Overview and principle
PWA Storefront Pack adds three independent but complementary building blocks to your WooCommerce store:
- Web App Manifest — customers can install your store on their home screen like a real native app (icon, splash screen, standalone mode without address bar).
- Service Worker — intelligent page and asset caching, customizable offline page, automatic exclusions of sensitive areas (cart, checkout, my-account).
- VAPID push notifications — full Web Push protocol implementation in pure PHP: ECDSA P-256, JWT ES256, aes128gcm encryption. Your server speaks directly to browser push services.
No third-party service. Unlike most WordPress push solutions, no customer data transits through an intermediary. Your VAPID keys are generated and stored on your server. You speak directly to FCM (Google), Mozilla autopush, WNS (Microsoft), etc.
Requirements
- WordPress 6.0 or later
- WooCommerce 7.0 or later
- PHP 7.4 or later with the
opensslextension (enabled by default on all hosts) - HTTPS required — browsers refuse to register a Service Worker or handle push notifications over HTTP (except localhost for development)
If your site is not yet on HTTPS, enable it before installing the plugin. All PWA features will be silently disabled over HTTP.
Installation
- Download the
pwa-storefront-pack.ziparchive from your DataFirefly account. - In WordPress, go to Plugins → Add New → Upload Plugin.
- Select the ZIP and click Install Now, then Activate.
- On activation, the plugin creates three SQL tables (
wp_pwasp_subscriptions,wp_pwasp_push_log,wp_pwasp_stock_waitlist) and automatically generates your VAPID key pair. - Go to WooCommerce → PWA Storefront to configure.
General configuration
The General tab centralizes your app identity:
- Enable PWA — master switch. Turn off to temporarily remove the manifest and Service Worker without uninstalling the plugin.
- App name — full name shown on install prompt and splash screen (e.g. “My Official Store”).
- Short name — short label under the home screen icon, capped at 12 characters per Android convention.
- Theme color — color of the address bar and task switcher (recommended: your primary brand color).
- Background color — splash screen background while the app loads (usually white or very light).
Endpoint URLs
The plugin serves two critical endpoints:
https://your-site.com/pwasp-manifest.json— the Web App Manifesthttps://your-site.com/pwasp-service-worker.js— the Service Worker
Important for cache plugins: these two URLs must always be served fresh. Add them to the exclusion list of WP Rocket, W3 Total Cache, LiteSpeed Cache, or your CDN. Otherwise configuration updates will never reach browsers.
Manifest
The Manifest tab controls the behavior of the installed app:
- Display mode —
standaloneby default (recommended, app-like experience). Other options:fullscreen,minimal-ui,browser. - Orientation —
any,portraitorlandscape. On mobile,portraitis often best for stores. - Start URL — path where the app opens at launch. Defaults to
/. You can point to/shopto open the catalog directly. - Scope — URL scope controlled by the app. Usually
/. Only restrict it if you only use the PWA on a subfolder. - Categories — hints for web app stores (Chrome, Edge). Example:
shopping,business. - Shortcuts — enable to generate Shop / Cart / My Account shortcuts accessible via long-press on the home screen icon.
App icons
The Icons tab lets you associate icons from the WordPress media library. Five formats are handled:
- Icon 192×192 (any purpose) — required. Used on Android, in search engine results.
- Icon 512×512 (any purpose) — required. Splash screen icon at launch.
- Maskable 192×192 — optional. With 10% inner safe zone for Android adaptive icons (circle, square, teardrop shapes).
- Maskable 512×512 — optional. Same principle for the splash screen.
- Apple Touch Icon 180×180 — for iOS. Square, no rounded corners (iOS adds them automatically).
Maskable icon tip: use a tool like maskable.app to generate your maskable variants with the correct safe zone. A logo without safe-zone padding will be cropped on some Android phones.
As long as no icon is configured, the plugin uses default icons shipped with it (DataFirefly branding). Replace them before going to production.
Offline mode and cache strategy
The Offline & Cache tab configures Service Worker behavior:
Strategies
- Network first (recommended) — the browser tries the network first, then falls back to the cache if offline. Maximum freshness of prices and stock.
- Cache first — the cache responds immediately, the network updates in the background. Faster but may display slightly stale prices.
Strategies only apply to HTML pages. Other resource types have fixed optimal strategies:
- CSS / JS / fonts → cache-first (they only change on version updates)
- Product images → stale-while-revalidate (immediate display from cache, refresh in background)
Cache scope
Three checkboxes allow you to enable/disable caching per type:
- Cache HTML pages — product pages, category, home page, posts
- Cache CSS / JS / fonts — your theme skeleton
- Cache images — product visuals, blog post images
Always excluded from cache (regardless of configuration): /wp-admin/, /wp-login.php, /cart, /checkout, /my-account, all WooCommerce AJAX endpoints. These areas require fresh, authenticated state at all times.
Offline page
Two options:
- Use the default screen — minimalist screen built into the plugin (icon, message, Try again button), in your brand colors.
- Use a custom page — select an existing WordPress page. It will be pre-cached at Service Worker install and served on network failure.
Install banner
The Install Banner tab controls install promotion:
- Delay (page views) — number of page views before showing. 3 by default: the user has expressed minimum interest without being harassed on first visit.
- Banner title / text / CTA / Dismiss — fully customizable copy, translatable via
.pot.
Behavior:
- On Chrome, Edge, Opera, Samsung Internet: the banner appears when the browser signals the site is installable (
beforeinstallprompt). A click on the CTA displays the native install dialog. - On iOS Safari: the banner automatically displays the “Tap Share, then Add to Home Screen” instructions (Apple offers no programmatic install API).
- Dismissal remembered 7 days — if the user dismisses the banner, it does not reappear for a week.
- Automatic detection — if the app is already installed (standalone mode detected), the banner no longer appears.
Push notifications: VAPID keys
Push notifications use the VAPID protocol (Voluntary Application Server Identification), a W3C standard. On plugin activation, an ECDSA P-256 key pair is generated automatically:
- Public key — shared with subscribers’ browsers (via JavaScript). 65 bytes, base64url-encoded.
- Private key — never transmitted, used to sign each send. 32 bytes.
The Push Notifications tab displays your public key in clear and the count of active subscriptions. You can copy it for external tests.
Key regeneration
The Regenerate keys button generates a new pair. This operation is destructive:
Regenerating keys immediately invalidates all existing subscriptions. The plugin automatically empties the subscription table after confirmation. Subscribers’ browsers will still receive already-signed notifications, but any new notification will silently fail until the user re-subscribes.
Only regenerate keys in case of proven compromise or when migrating between environments.
VAPID subject
VAPID subject field: contact address in mailto:you@example.com or https://example.com/contact format. Some push services (notably Mozilla) use it to reach you if abuse is detected from your server. Pre-filled with the WordPress admin email.
Opt-in prompt and GDPR
The Opt-in prompt section configures the pre-prompt shown before the native permission dialog:
- Show opt-in prompt — activates the customized pre-prompt. Recommended: the native dialog alone has a high refusal rate and blocks any new request for 30 days.
- GDPR consent required — never triggers the native dialog without explicit user click on your CTA. Required in Europe for GDPR compliance.
- Delay (seconds) — wait time before display. 10 seconds by default: let the user explore before soliciting permission.
- Prompt title / text / CTA / Dismiss — fully customizable copy.
Best practices: explain the value for the user (“Track your orders in real time”), not for you (“Stay tuned to our offers”). Acceptance rate is 3 to 4 times higher.
Automated triggers
The plugin ships with three automations wired directly into WooCommerce hooks. Each can be toggled independently.
Order status
Hook: woocommerce_order_status_changed.
The identified customer (not guests) receives a notification on every order status transition. Title: “Order #1042 updated”. Body: “Status: Shipped”. Click → order tracking page.
The notification uses a unique tag per order (order-1042): successive updates replace the previous one instead of stacking.
New order (admin)
Hook: woocommerce_new_order.
All users with administrator or shop_manager role subscribed to push receive a notification on every new order. Title: “New order received”. Body: “Order #1042 — $189.00”. Click → order edit screen.
The admin URL is HPOS-aware: if your WooCommerce uses High-Performance Order Storage, the link points to the new schema (admin.php?page=wc-orders). Otherwise to the old one (post.php?post=X).
Back in stock
Hooks: woocommerce_product_set_stock and woocommerce_variation_set_stock.
When a product goes from “out of stock” to “in stock”, the plugin sends a notification to every visitor who added themselves to its waitlist. Title: “Back in stock!”. Body: “Premium leather sneakers limited edition is available again”. Product image as preview when available.
Each entry is marked notified_at after successful send to avoid duplicates if stock oscillates.
Broadcast composer
Menu: WooCommerce → PWA Broadcast. Interface to send a manual notification to all active subscribers (marketing campaigns, announcements, etc.).
Fields:
- Title — notification title (100 characters max recommended)
- Message — notification body (200 characters max recommended)
- Open URL — page where the user lands on click (defaults to the home page)
- Image URL — large image shown in the notification (Android only, iOS doesn’t display it)
A live preview shows an approximate rendering of the notification on the right side of the screen.
Two buttons:
- Send broadcast — send to all active subscribers (confirmation required)
- Send test to me — send only to your own subscriptions. Useful to validate rendering before a mass broadcast.
Timing: avoid broadcasts in the middle of the night — on Android, notifications ring by default. A Friday-evening 9 PM send has a click-through rate 2× higher than a 3 AM send.
Back-in-stock waitlist (JavaScript API)
To let visitors sign up for the waitlist of an out-of-stock product, call from your theme:
window.PWASP.addToWaitlist(productId)
.then(result => {
if (result.success) {
alert('You will be notified as soon as it is back in stock!');
}
});
Behavior:
- If the user is not yet subscribed to push, the native permission dialog opens.
- Once the subscription is registered server-side, the entry is added to the product waitlist.
- When back-in-stock is detected, a push is sent automatically.
You can call this API from any custom button or via a mu-plugin hooked into woocommerce_single_product_summary.
Other JS APIs exposed
// Subscribe manually (e.g. from a custom button)
window.PWASP.subscribePush();
// Unsubscribe ("Unsubscribe me" button)
window.PWASP.unsubscribePush();
REST API
The plugin exposes six endpoints under the pwasp/v1 namespace:
POST /wp-json/pwasp/v1/subscribe— registers a subscription. Body: browserPushSubscriptionobject.POST /wp-json/pwasp/v1/unsubscribe— removes a subscription. Body:{ endpoint: "..." }.POST /wp-json/pwasp/v1/test— test send to the current user (auth required,manage_woocommercecapability).POST /wp-json/pwasp/v1/broadcast— broadcast to all subscribers (auth required).POST /wp-json/pwasp/v1/regenerate-vapid— regenerates VAPID keys (auth required).POST /wp-json/pwasp/v1/waitlist— adds to a waitlist. Body:{ subscription_id, product_id }.
Authentication: WordPress X-WP-Nonce for public endpoints, manage_woocommerce capability for admin endpoints.
Compatibility and edge cases
HPOS (High-Performance Order Storage)
The plugin formally declares HPOS compatibility to WooCommerce via FeaturesUtil::declare_compatibility. You’ll see the checkbox ticked in WooCommerce → Settings → Advanced → Features.
Cache plugins
Add the following exclusions to your cache plugin:
/pwasp-manifest.json/pwasp-service-worker.js
Some plugins (WP Rocket, LiteSpeed) also offer an option to not cache Service Worker JavaScript files — enable it if available.
iOS and Safari
Support by version:
- iOS 16.4 and later — installation via “Add to Home Screen” and push notifications (for installed PWAs only)
- iOS 15 and 16.3 — installation possible, push notifications unavailable
- iOS 14 and earlier — installation possible, no notifications
On iOS, push only works if the user has first installed the PWA to their home screen. This is an Apple constraint, not the plugin’s.
Subfolders and multisite
The plugin works on WordPress installed at the root (example.com) or in a subfolder (example.com/shop/). Endpoints are resolved dynamically via home_url(). On multisite, activate the plugin per site — each site will have its own VAPID key pair and its own subscriber base.
Troubleshooting
“The Service Worker is not registered”
- Verify your site is on HTTPS (
https://and nothttp://). - Open the browser console (F12 → Application tab → Service Workers). Is there an error message?
- Test the URL
https://your-site.com/pwasp-service-worker.jsin a tab. The file should return JavaScript, not a 404 page or the WordPress home. - If 404: go to Settings → Permalinks and click Save Changes to refresh rewrite rules.
“Notifications don’t arrive”
- Check in WooCommerce → PWA Subscribers that your subscription is listed and in active status.
- Use the Send test to me button in the broadcast composer. Do you receive the notification?
- If not: the permission dialog may have been declined. On Chrome: open the padlock in the address bar → Notifications → Allow.
- On Windows/macOS: check that Chrome/Firefox is not in “Do Not Disturb” mode.
“VAPID key regeneration failed”
Likely cause: the openssl PHP extension is not available on your hosting, or ECDSA key generation is blocked. Check via a phpinfo.php file that the openssl section is present and the prime256v1 curve is supported. Contact your host if needed.
Uninstallation
Removal via Plugins → Installed Plugins → Delete:
- The three SQL tables are dropped
- Plugin options are removed
- Scheduled cron tasks are cancelled
- Icons uploaded to the media library remain (they may be used elsewhere)
Support
For any question or issue, open a ticket from your DataFirefly account. Response within 24 business hours.