WooCommerce plugin

A WordPress plugin that fills the E-commerce (RFM) dashboard from your store — orders, carts, product views and history — without touching your theme or slowing checkout.

Install the plugin, paste one connect code, import your order history. Every component of the E-commerce (RFM) template is fed, and past orders are imported so the scores mean something on day one rather than in ninety days.

Requires WordPress 6.0+, WooCommerce 7.1+, PHP 7.4+. Works with High-Performance Order Storage and the cart/checkout blocks.

Set up

One paste, not two fields

The connect code carries the ingest URL and the key together, and your project is resolved from the key itself — so there is no URL to mistype and no project id to look up.

  1. Settings → Integrations → WooCommerce in ChurnWarn — create a key for the store and copy the connect code.
  2. In WordPress: Plugins → Add New → Upload Plugin, upload the zip, activate.
  3. WooCommerce → Settings → Integrations → ChurnWarn — paste the code, save. The screen turns green and names the project it connected to.
  4. Click Import order history.

What it sends

SignalWhenComponent it feeds
order_placedOrder reaches Processing or CompletedRecency, Frequency, Monetary — 62% of the score
order_returnedRefund recorded, full or partialReturn rate
cart_createdFirst item added to a known customer's cartCart abandonment (denominator)
cart_abandonedCart untouched for the configured windowCart abandonment
product_viewedKnown customer opens a product pagePurchase conversion
referralOrder uses a coupon matching your referral prefixesReferrals (opt-in)

Account facts are written too — kind: person, valueBasis: ltv, lifetime spend, order count, first and last order — which is what makes the dashboard read LTV at risk. Account silence, the eighth component, needs no signal of its own.

Cart and view history do not exist in WooCommerce, so those three components start empty and fill forward. Everything else backfills.

Privacy

Pseudonymous by default, matching the other SDKs:

  • A registered customer becomes wc_{user_id}.
  • A guest becomes wcg_{HMAC-SHA256(email, site salt)} — one account across repeat guest orders, and an id nobody can turn back into an email. The salt is generated on the merchant's site and never transmitted.
  • Payloads carry numbers, ids and booleans. Never addresses, phone numbers or free text, and everything is scrubbed with the same masking the other SDKs use before it leaves.

Switching Customer identity to Identified sends names and emails, for merchants who run win-back campaigns from the dashboard. It is the only setting that sends personal data, and switching it re-keys accounts — re-run the import afterwards.

Behavioural signals honour the WP Consent API (statistics) when a consent plugin is installed. Order records are treated as business records; the churnwarn_should_track filter overrides either.

Settings worth a second look

Cart abandoned after — 240 minutes (4 hours) by default, adjustable from 15 minutes to 7 days. It feeds a scored component directly, so set it to your own repurchase rhythm: a grocery cart is stale in an hour, a furniture cart is still live after two days.

Browser tracking — on by default. Cached product pages never reach PHP, so server-side view tracking under-counts on any store running a page cache, and a conversion rate with a missing denominator is worse than none. With this on, views are reported from the storefront and server-side view tracking switches itself off so nothing is counted twice.

Report values in — base currency by default. A multi-currency store reporting in order currency would have 100 EUR and 100 JPY summed as "200".

Count an order when it becomes — leave it on the default. Both transitions are wired and the shared idempotency key means the second one is ignored, not double-counted.

Re-running anything is free

Every event carries a deterministic idempotency key — wc:{install}:order:{id}:placed — and ChurnWarn keeps the first event it sees for a key and ignores the rest. So a re-run of the importer, a retry after a timeout, and a WooCommerce hook that fires twice all converge on exactly one event.

It cannot break the store

Design constraint, not a hope

A ChurnWarn failure — API down, key revoked, table missing — must cost the merchant nothing. Our code runs inside their checkout, so this gets more attention here than in any other SDK.

  • No network I/O on any request a shopper waits for. Producing an event is one INSERT. Delivery happens in Action Scheduler jobs, plus an opportunistic flush on shutdown that only runs after fastcgi_finish_request() has already handed the page over.
  • One fault barrier. Every callback is registered through a wrapper that swallows Throwable and, for filters, returns the input untouched.
  • A kill switch. Twenty consecutive failures, or any 401/403, pauses sending and raises an admin notice — no retry storm against a dead endpoint.
  • Bounded everything. 50k queued rows max (oldest shed and counted), 200 events per request, 200 enqueues per page load.
  • Staging clones are detected by site-URL fingerprint and paused, so a copy of production cannot post test orders into the live dashboard.

Filters

FilterPurpose
churnwarn_should_track( bool $allowed, string $context )Veto any signal. $context is transactional or behavioural.
churnwarn_order_exchange_rate( float $rate, WC_Order $order, string $base )Supply a rate when your multi-currency plugin is not one of the ones read automatically.

Next