DataFirefly Push — Complete guide
Install, configure and operate native Web Push notifications for WooCommerce: auto-generated VAPID keys, multi-style opt-in with pre-prompt and A/B test, ten automatic triggers, campaigns with visual builder and behavioural segmentation, complete analytics and customer My Account page.
Overview and requirements
DataFirefly Push turns your WooCommerce store into a native Web Push notifications platform. No SDK, no third-party tracking: every piece of cryptography (VAPID and RFC 8291 encryption) runs on your own server in pure PHP through OpenSSL. The plugin covers a multi-style smart opt-in, ten automatic triggers, manual campaigns with visual builder and segmentation, a complete analytics dashboard, a dedicated My Account page for your customers, and native GDPR compliance.
- WordPress 6.2 and above.
- WooCommerce 7.0 and above, tested up to 9.6, HPOS and Cart/Checkout Blocks compatible.
- PHP 8.1 and above.
- Multilingual (FR/EN/ES/DE/IT), compatible with Polylang and WPML.
- Compatible with LiteSpeed Cache, WP Rocket and other cache plugins: the Service Worker is served as standalone PHP.
No third-party service to plug in, no Composer library to maintain. VAPID keys are generated automatically on activation, subscriptions and events stay in your own database.
Installation
- Download the
df-push.ziparchive from your customer account. - In the WordPress admin, go to Plugins > Add New > Upload Plugin and drop the archive.
- Click Activate.
- The DF Push menu appears in the admin sidebar with seven sub-menus: Dashboard, Campaigns, Subscribers, Triggers, Opt-in, Settings, Webhooks & API.
On activation, the plugin creates eight dedicated tables prefixed dfpush_, generates your VAPID keys, schedules the daily cron df_push_daily_lifecycle and registers the My Account endpoint. No manual step is needed.
First-time setup: VAPID keys and opt-in
Once activated, the plugin is immediately functional with its default settings: the floating bell appears bottom-right after five seconds, the pre-prompt is enabled, automatic triggers are ready. Just check two things in DF Push > Settings before announcing the service:
- VAPID public key: the block shows your automatically generated public key (the application server key used by the browser). You can regenerate it but that invalidates every existing subscription.
- PWA manifest and default icon: add your icon (192×192 minimum) if
site_iconisn’t set on the site.
No external service to register, no Firebase / OneSignal developer account to create. The VAPID keys the plugin generates are enough: they authenticate your application server with the FCM, Mozilla Push and WNS push services.
Opt-in tab — prompt, styles and triggers
This tab drives the subscription request. Five available styles, each positionable and themeable:
- Floating bell (default): discreet pill bottom-right or bottom-left.
- Banner at the top or bottom of the page.
- Modal centered with overlay.
- Slide-in from the side.
- Sticky bar pinned at the top.
The soft-ask pre-prompt (recommended) shows your custom message before the browser’s native request. This mechanism preserves your opt-in quota: on Chrome, declining the pre-prompt doesn’t burn the native-request budget (×3 vs 1 without a pre-prompt).
Five configurable, stackable triggers:
- Delay (in seconds) after page load.
- Scroll as a percentage of the page (0 = disabled).
- Exit-intent on mouse-leave motion (desktop only).
- X pages viewed in the session.
- Add to cart (captures the WooCommerce
added_to_cartevent).
Enable the prompt A/B test with a variant B title and message, and a configurable split. Assignment is persisted in localStorage to ensure per-visitor consistency across sessions.
Once the browser permission is denied, it can’t be re-requested by script. Polish your pre-prompt and don’t chain a request on the first scroll: that pattern shows 70 % refusal versus 20-30 % with a pre-prompt fired at the right moment.
Triggers tab — the automatics
Ten automatic triggers, each individually toggleable from the Triggers tab. Each relies on Action Scheduler for deferred sends, with a synchronous fallback if Action Scheduler isn’t available.
Abandoned cart
Three configurable reminders, by default at 1 hour, 24 hours and 72 hours after abandonment. Detection captures the added_to_cart event for Push-subscribed users and schedules three df_push_abandoned_cart actions at decreasing intervals. Reminders are automatically cancelled if the order is placed meanwhile.
Back-in-stock
On the product page, your subscribed visitors can join a per-product waitlist. When WooCommerce fires woocommerce_product_set_stock_status with a return to instock, the plugin sends a notification to the product’s waitlist, then empties it.
Price drop
The plugin keeps a _df_push_last_price meta per product. On every product update, it compares the old and new price. If the drop exceeds the configured minimum percentage threshold, a notification is sent to the Promotions topic.
Confirmation, shipping, review
- Order confirmation: immediate send on
woocommerce_thankyouto the subscriber if the user ID matches. - Shipping: detects the tracking number on the order by reading in order the meta
_tracking_number,_wc_shipment_tracking_items(WooCommerce Shipment Tracking) and_aftership_tracking_number(AfterShip). If a number is found, the notification includes it in its message. - Review request: scheduled X days after the order moves to the completed status (configurable delay).
Birthday, re-engagement, new product
- Birthday: the daily cron
df_push_daily_lifecyclereads the WooCommercebilling_birthdayfield and sends a notification to subscribers whose birthday it is. - Re-engagement: sends to subscribers inactive for 30, 60 and 90 days (windows configurable as CSV:
30,60,90). - New product: on product publish, a notification is sent to the New arrivals topic.
Every trigger accepts a templated payload: {firstname}, {product_name}, {product_price}, {old_price}, {order_number}, {tracking_number}, {category}, {discount_code}. Variables are resolved at send time, not at scheduling time.
Campaigns tab — visual builder, segmentation, A/B test
Build a manual campaign in DF Push > Campaigns > New campaign. The builder offers a live preview of the notification as it will appear on the subscriber’s device.
- Content: title, message, destination URL, hero image, up to two action buttons with their own label and URL.
- Persistent notification (requireInteraction option): the notification stays visible until interaction.
- Segmentation by language, country, device, topic, and by RFM behaviour: minimum orders, minimum AOV, days inactive, purchased category. Behavioural segments are computed via
wc_get_ordersat launch. - A/B test: enable a variant B (title and message), the split is configurable in percent. Assignment is random per subscriber, deterministic by ID for analytics consistency.
- Scheduling: pick a date and time, or send immediately.
- Test mode: send the campaign to admins only, from the builder, before going live.
The send engine automatically chunks the segment, respects per-subscriber timezone quiet hours, applies the configured frequency cap, and purges on the fly any endpoint returning 404 or 410 (browser-side unsubscribe).
Dashboard and analytics
The DF Push > Dashboard screen aggregates your 30-day KPIs. Chart.js is bundled locally (no external CDN dependency).
- KPIs: active subscribers, opt-in rate, sends, click-through rate (CTR), conversions, attributed revenue.
- 30-day time series: sends vs clicks, one line per day.
- 7 × 24 heatmap: best send slots based on clicks, crossing day of week and hour of day.
- Per-campaign funnel: sent > delivered > clicked > converted.
- Attributed revenue: a configurable attribution window (72 hours by default) links each click to the first purchase made within the window by that subscriber.
- CSV export of every event for GDPR audit or BI integration.
Customer page: My Account → Notifications
A dedicated My Account → Notifications page is automatically added to the WooCommerce dashboard. The customer gets four blocks:
- This device: current status (active, disabled, blocked by browser, unsupported), with Enable or Disable on this device button.
- All your devices: list of subscribed devices (type, browser, language, last activity), with per-device unsubscribe or unsubscribe-all in one click.
- My preferences: checkboxes for the native topics (New arrivals, Promotions, Back in stock). Saved via REST with confirmation.
- Notification history: the last 30 notifications received, with title, body, icon, link and date.
The URL is /my-account/df-push-notifications/ in English. The rewrite endpoint is registered with the EP_ROOT | EP_PAGES mask, with a self-heal on init:999 that detects a missing rule (concurrent permalink flush case) and re-flushes automatically.
Customer-side actions (unsubscribe, preferences) go through REST routes under df-push/v1/account/*, authenticated by cookie + wp_rest nonce. No action can be performed on another account, even if the device identifier is tampered with in the request.
GDPR and consent register
GDPR compliance is handled natively, not as a cosmetic add-on. Every opt-in and unsubscribe is recorded in the dfpush_consent_log table with:
- Subscriber ID.
- Action: subscribe or unsubscribe.
- SHA-256 hashed IP (the cleartext IP is never persisted).
- User-agent.
- UTC timestamp.
The native WordPress Privacy Exporters and Erasers are wired in: a customer can request export or deletion of their personal data from Tools → Export Personal Data or Tools → Erase Personal Data. The plugin then includes their subscriptions, topics, inbox and consent register in the response — or removes them as requested.
Settings tab — anti-spam and attribution
This tab centralizes subscriber-respect parameters and the attribution window:
- Quiet hours: interval during which no notification is sent. Timezone-aware (read on the subscriber’s device at opt-in time via
Intl.DateTimeFormat().resolvedOptions().timeZone). 22h-8h local by default. - Frequency cap: maximum number of notifications per day per subscriber. 0 = unlimited.
- Smart send time: optimises send time per subscriber based on their historical click slots.
- Attribution window: duration in hours between a click and an order for the order to be attributed to the notification. 72 hours by default.
- In-site inbox: enables or disables the floating bell with notification history on the front-end.
- PWA manifest: enables manifest generation to make the site installable on mobile.
Webhooks and REST API tab
The Webhooks & API tab covers two integration mechanisms.
Outbound webhooks
Configure one or more HTTP endpoints per event. Three formats are available:
- Slack:
{ text }payload compatible with Slack Incoming Webhooks. - Discord:
{ content }payload compatible with Discord Webhooks. - Generic: full JSON payload with event, timestamp, data — Zapier, n8n, Make-compatible.
Available events: subscriber.created, campaign.launched, notification.clicked, order.attributed. Requests are non-blocking (wp_remote_post with blocking=false) so they never slow down the main send.
REST API
Under the df-push/v1 namespace, the plugin exposes a tokenised public send route: POST /wp-json/df-push/v1/send with the X-DF-Push-Token header. The token is regeneratable in one click from the admin.
curl -X POST https://your-site.com/wp-json/df-push/v1/send
-H "Content-Type: application/json"
-H "X-DF-Push-Token: YOUR_TOKEN"
-d '{
"title": "Flash promo",
"body": "20 % off the whole catalogue until midnight",
"url": "https://your-site.com/promotions",
"segment": { "lang": "en", "topic": "promos" }
}'
Treat this token like a password. Anyone who has it can send notifications to your subscribers. Regenerate it immediately if you suspect a leak.
In-site inbox, PWA and multilingual
Three complementary features cover cases where the user hasn’t allowed Push.
- In-site inbox: a floating bell (front-end configurable) opens a list of the latest notifications received by the user, read or unread, even if they’ve never allowed Push. Particularly useful for iOS Safari before 16.4 and PWA users.
- PWA manifest: dynamically generated at
/df-push-manifest.jsonfromsite_iconor a custom icon.df_push_manifestfilter available to adjust theme color, display, scope, start_url. - Multilingual: Polylang and WPML compatible. Notifications are sent in the subscriber’s language (detected at opt-in), with fallback on the site’s default language.
.poand.mofiles in FR, EN, ES, DE, IT are included.
Service Worker and technical architecture
The Service Worker is served by a standalone PHP file at /wp-content/plugins/df-push/sw.php. This approach completely sidesteps WordPress routing: no chance of interference with a cache plugin, a canonical redirect or another template_redirect handler.
The Service-Worker-Allowed: / header is sent in response to allow registration with root scope (scope: '/') even though the script lives under /wp-content/.
On the database side, eight tables prefixed dfpush_:
dfpush_subscribers: subscribers and their Push endpoint.dfpush_topic_subs: topic ↔ subscriber assignments.dfpush_campaigns: manual campaigns with payload, segment and scheduling.dfpush_notifications: log of individual sent notifications.dfpush_events: raw events (opt-in, sent, delivered, clicked, converted) for analytics.dfpush_inbox: persistent copy of notifications for the in-site inbox.dfpush_stock_waitlist: back-in-stock waitlists.dfpush_consent_log: GDPR register.
Uninstall (full delete from Plugins) drops these eight tables and purges every option. Simple deactivation, on the other hand, keeps the data for later re-activation.
Developer hooks
The plugin exposes actions and filters at key points to extend its behaviour without touching the core.
df_push_booted(action): fires after plugin boot, useful to register custom extensions.df_push_payload_build(filter): alter the JSON payload sent to the push service before encryption.df_push_should_send(filter): short-circuit the send on custom conditions (return false to skip).df_push_segment_query(filter): enrich behavioural segmentation criteria.df_push_webhook_payload(filter): adjust outbound webhook payloads.df_push_manifest(filter): alter the generated PWA manifest.- Registered Action Scheduler actions:
df_push_send_one,df_push_fan_out,df_push_abandoned_cart,df_push_review_request,df_push_dispatch_campaign.
FAQ and troubleshooting
The opt-in prompt doesn’t show up
Three possible causes: browser permission is already denied (check your browser settings), permission is already granted (the prompt isn’t needed anymore), or a trigger hasn’t fired yet (delay not elapsed, insufficient scroll). In the JavaScript console, run window.DFPush.isSubscribed() to check current state.
The Subscribers admin is empty even though an opt-in succeeded
Check in the network console that the POST /wp-json/df-push/v1/subscribe request returns a 200 code. From version 1.0.1, the plugin automatically re-syncs any existing PushSubscription with the server on every page load, and logs any DB insertion error to error_log.
The Service Worker fails to register
If the browser error is “The script resource is behind a redirect” or “Unexpected token ‘<‘”, test directly the URL https://your-site.com/wp-content/plugins/df-push/sw.php. You should see the Service Worker JavaScript code with Content-Type: application/javascript and the Service-Worker-Allowed: / header. If you see HTML 403, check the htaccess rules that may block direct PHP execution under wp-content/plugins/.
Notifications aren’t received on iOS
Safari on iOS only supports Push notifications from version 16.4 and only for sites installed as a PWA via the Add to Home Screen button. The PWA manifest generated by the plugin makes that installation easy. If you don’t specifically target iOS, this isn’t an issue: other browsers receive notifications normally.
How to migrate from OneSignal or Pusher
Existing subscribers on those third-party services aren’t portable: Push cryptography ties each subscription to a unique pair (server VAPID key, browser endpoint). Your visitors will have to re-subscribe after your switch to DataFirefly Push. You can prepare the transition by disabling the old SDK a few days in advance and communicating via a pre-announcement banner about the new experience.
What happens on uninstall?
Simple deactivation keeps every table and option: you can reactivate the plugin and pick up where you left off. Full delete from Plugins runs uninstall.php which drops the eight dfpush_ tables, purges every plugin option (including VAPID keys and the API token), and unschedules the crons. Permalinks are automatically flushed on the next request.