Docs / Setup guide

COD Order Protection · Beta

COD offline conversions using server GTM

Hold Cash on Delivery (COD) purchases at checkout, verify the order in WooCommerce or your dashboard, then fire a real Purchase to Meta Conversions API, Google Ads, and GA4 through your server-side GTM container — backdated to the original event_time with email, phone, fbp, and gclid preserved.

Similar to Stape's offline conversion guide, but built into PixelFly with a held-events dashboard, monthly fire quota, and first-party /cod/hold endpoints. For CRM / order-status webhooks → Meta CAPI, see the CRM webhook guide. To restore missing email, phone, and fbp on fire, see EMQ Enricher.

What are COD offline conversions?

A COD order is placed online, but payment happens later — often days after delivery. If you fire Purchase at checkout, Meta and Google optimize for people who place orders, including fakes and cancellations (30–50% in many COD markets).

Offline / delayed conversion tracking waits until the order is confirmed, then sends the conversion with the original checkout timestamp. Meta matches using hashed email, phone, _fbp, _fbc, and click IDs captured at checkout.

Why use PixelFly COD Order Protection?

  • Hold at checkout — sGTM sends COD to {your-domain}/cod/hold; nothing hits ad platforms yet.
  • Dashboard review — approve, reject, or auto-confirm via WooCommerce webhook.
  • Fire through sGTM — confirmed orders POST to /data → Data Client → your Meta / Google Ads / TikTok tags.
  • Prepaid unchanged — non-COD orders fire immediately (browser + server), not stored in held events.
  • First-party endpoints — same custom domain as your sGTM loader (e.g. server.yourstore.com).

Architecture (sGTM container)

Checkout (COD)
  → Web GTM: purchase + payment_method=cod → sGTM
  → sGTM: PixelFly COD Protection tag → POST /cod/hold
  → PixelFly: held_events (pending)

Order confirmed (manual or webhook)
  → PixelFly: Approve & Fire
  → POST {host}/data (Purchase, original event_time)
  → sGTM Data Client → Meta CAPI / Google Ads / GA4
Suppress duplicate Purchase tags: browser and sGTM Purchase tags must not fire for COD at checkout. Use trigger payment_methodcod for prepaid only.

Step 1 — Enable COD Order Protection in PixelFly

  1. Open your container in the PixelFly dashboard → Power-ups.
  2. Enable COD Order Protection (Beta).
  3. For sGTM containers, choose fire path:
    • sGTM /data — required for Google Ads (recommended).
    • Receivers /e — Meta + GA4 via PixelFly receivers only.
  4. Copy Hold URL, Webhook URL, and Webhook secret.

Step 2 — WooCommerce plugin (GTM mode)

  1. Update to PixelFly plugin v1.2.0+.
  2. Go to PixelFly → COD Order Protection.
  3. Set COD Handling ModeGTM / sGTM (recommended).
  4. Ensure DataLayer is enabled — the plugin pushes purchase with payment_method on the thank-you page.
  5. Optional: enable Auto-confirm webhook and paste the webhook secret to fire when Woo status becomes Processing / Completed.

Step 3 — Import PixelFly COD tag (server GTM)

  1. Download the sGTM tag template:

Download sGTM COD template (.tpl)

  1. Server GTM → Templates → Tag Templates → New → Import.
  2. Create tag: host = your server domain, API key = container key, trigger = purchase AND payment_method equals cod.

Step 4 — Web GTM: prepaid vs COD

  • Always send purchase to sGTM (include payment_method, email, phone, items).
  • Browser Meta / Google Purchase tags: trigger only when payment_methodcod.
  • sGTM Meta / Google Purchase tags: same — prepaid only at checkout.

Step 5 — sGTM Preview header (debug webhooks & /data)

When testing confirm/fire flows in GTM Preview (like Stape's preview header setup):

  1. Server GTM Preview → ⋮ → Send requests manually → copy X-Gtm-Server-Preview.
  2. PixelFly dashboard → Power-ups → sGTM Preview header → paste header → Save.
  3. Turn off the power-up after testing so live traffic is not sent to Preview.

Step 6 — Data Client + Meta CAPI tag (on fire)

  1. Install Stape (or compatible) Data Client in server GTM; accept path /data.
  2. Add Facebook Conversions API tag (Gallery) — trigger: Custom Event purchase, Client Name = Data Client.
  3. Add Google Ads Conversion tag on the same trigger if you use Google Ads (requires gclid at hold time).

When you approve a held order with fire path sGTM /data, PixelFly replays purchase with is_delayed: true and the stored identifiers.

Step 7 — Proxy containers (no sGTM)

If you use a PixelFly proxy container instead of sGTM:

  • Download the web COD template and hold from the browser via sendPixel GET to /cod/hold.
  • Do not import the sGTM COD template into a web container.
  • Fire path is always Receivers /e (no Google Ads via receivers — use sGTM for Ads).

Download web COD template (.tpl)

Step 8 — Test end-to-end

  1. Place a test COD order — check sGTM Preview: COD Protection tag fires.
  2. PixelFly → COD Held Orders — row appears as pending.
  3. Approve & Fire — check sGTM Preview for /data purchase.
  4. Meta Events Manager → verify Purchase with correct value and match quality signals.

Improve Event Match Quality (EMQ)

Capture identifiers at hold time (not only at fire). To restore missing fbp / email / phone on the fire itself, enable EMQ Enricher (Pro+) — it fills empty CIP on POST /data without replaying PageViews.

Store at hold:

  • Hashed-ready email and phone from checkout
  • _fbp and _fbc (first-party cookies)
  • gclid for Google Ads click attribution
  • Client IP and user agent (sGTM receives these automatically)

The PixelFly plugin and GTM templates pass these fields; the held row stores them encrypted until fire.

FAQs

Is this the same as Facebook offline conversions?

Same goal — send conversions after the real sale — but COD orders originate on your website. Use action_source: website and the original checkout event_time, not offline CSV uploads.

Do prepaid orders go into Held Events?

No. Only COD is held. Prepaid fires immediately via normal GTM tags to avoid database load at scale.

Can I auto-fire on WooCommerce status change?

Yes. Enable the webhook in the plugin or POST to /cod/webhook with your webhook secret when status is processing or completed.

What about legacy “Delayed Purchase Events” in the plugin?

Still available as Legacy mode for existing stores. New setups should use GTM / sGTM mode and this guide.

Ready to stop paying for fake COD conversions?

Enable COD Order Protection on your PixelFly container and follow this guide.

Get started free

We use cookies to enhance your experience, analyze site traffic, and for marketing purposes. By continuing to use our site, you consent to our use of cookies. Learn more