Ad platforms and webshops

WooCommerce server-side tracking: a setup guide

Set up WooCommerce server-side tracking: send paid orders to Meta and TikTok with the ROASaurus plugin or webhooks, match them to ad clicks and test.

·Updated ·11 min read·By the ROASaurus team

Key takeaways
  • WooCommerce server-side tracking sends each paid order from the shop's own order data to Meta, TikTok and other ad platforms, so a purchase counts even when the browser pixel never fires.
  • ROASaurus counts a WooCommerce order as paid when its status is processing or completed, which includes cash on delivery orders and bank transfers once you confirm them.
  • The ROASaurus plugin saves the visitor id and the ad click cookies on each order at checkout, so the order is linked to its ad click exactly.
  • Without the plugin, webhooks still deliver every paid order, but there is no thank-you page matching: orders are linked only by an email given earlier on the site or by a unique IP address and browser.
  • On WooCommerce the ROASaurus script follows consent plugins that use the WP Consent API, such as Complianz and CookieYes, and Cookiebot, OneTrust and IAB TCF banners.

WooCommerce server-side tracking sends each paid order from your shop's order data to Meta, TikTok and other ad platforms, instead of relying only on a pixel in the shopper's browser. The purchase is reported even when an ad blocker stops the pixel or the shopper never reaches the thank-you page.

This guide covers why WooCommerce stores lose conversions, the order data WooCommerce gives you, and the two ways to connect ROASaurus: the WordPress plugin or webhooks. Then matching, consent, setup and testing. For the general idea, read what server-side tracking is.

Why do WooCommerce stores lose conversions?

A browser pixel reports a purchase only when the pixel script loads, the shopper reaches the thank-you page and the browser sends the event. Each step can fail. The order itself is still in your database, because WooCommerce saves it on the server.

What happensBrowser pixelOrder data in WooCommerce
The shopper pays by redirect (for example PayPal or a bank app) and closes the tabNo thank-you page, no purchase eventPaid order, status processing
An ad blocker or privacy setting blocks the pixel scriptNo purchase eventPaid order
The visitor declines marketing cookiesThe pixel must not loadPaid order
A bank transfer is confirmed three days laterNo browser is open at that momentStatus changes from on hold to processing
A caching or script optimization plugin delays the pixelThe event can be late or missingPaid order
In every case the paid order exists in WooCommerce. Server-side tracking sends that order, whatever happened in the browser.

Missing purchases do two kinds of damage. The ad platform optimizes on fewer conversions, and your reports show a lower return than you really get. Here is the second effect in numbers, for an example store with a break-even ROAS of 2.2:

Example store, one monthPixel onlyEvery paid order
Meta ad spend$8,000$8,000
Purchases from Meta clicks260320
Revenue at $60 per order$15,600$19,200
ROAS15,600 ÷ 8,000 = 1.9519,200 ÷ 8,000 = 2.40
Against break-even (2.2)Looks like a lossProfitable
Illustrative numbers. The same campaign looks like a loss on pixel data and makes money on order data.

What WooCommerce gives you: orders, webhooks and the REST API

Which order statuses count as paid?

WooCommerce describes processing as payment received, with the order waiting to be fulfilled. ROASaurus sends orders with the status processing or completed and skips pending payment, on hold, failed, cancelled and refunded orders. Two payment methods need attention:

  • Cash on delivery. WooCommerce sets these orders to processing until the payment is collected, so ROASaurus sends them when they are placed. Orders with a downloadable product are the exception: they go on hold. See tracking cash on delivery orders for what that means for returns and refusals.
  • Bank transfer. WooCommerce puts these orders on hold while you verify the payment. ROASaurus sends them when you move them to processing.

Webhooks

A webhook is a message WooCommerce sends to another system when something changes. You create it under WooCommerce › Settings › Advanced › Webhooks. For an order topic, the payload is the same order object the REST API returns. Each delivery carries an X-WC-Webhook-Signature header: a base64 HMAC-SHA256 hash of the payload, made with the secret you choose. ROASaurus checks that signature before it accepts an order.

Two details matter in practice. WooCommerce delivers webhooks in the background, with WP-Cron by default, so a delivery can be delayed when that queue runs late. And WooCommerce disables a webhook after more than five failed deliveries in a row.

REST API

The REST API lets ROASaurus ask for orders itself. With a read-only API key, ROASaurus asks every 5 minutes for processing and completed orders changed since its last check, with 30 minutes of overlap. Orders it already has are ignored. This catches any order a webhook missed.

Order fieldWhat ROASaurus does with it
idBecomes the event id order-1042, shared by the server and browser events
totalThe purchase value: the grand total, including tax and shipping
Billing email, phone, name, city, state, postcode, countryHashed with SHA-256 and sent as customer data
customer_ip_address, customer_user_agentSent with the event and used to match the order to a visitor
line_itemsProduct ids (the variation id when there is one), quantities and prices
date_paid_gmtThe event time for orders from a webhook or the REST API (the creation date when there is no paid date)
meta_dataWith the plugin: the visitor id and the Meta and TikTok cookies
What ROASaurus reads from a WooCommerce order. The webhook and the REST API return the same fields.

Plugin or webhooks: two ways to connect

Both connections send every paid order. They differ in how well each order is linked to the ad click that brought the shopper in.

CheckoutThe plugin saves the visitor id and click cookies on the order
Order paidStatus processing or completed
ROASaurusReceives the order from the plugin or a webhook
Ad platformsMeta, TikTok and others get a Purchase with event id order-1042
The data path with the plugin. Without it, the checkout step saves nothing extra and the order arrives by webhook only.
ROASaurus pluginWebhooks only
What you installA WordPress plugin (PHP 7.4 and WooCommerce 6.0 or newer)Nothing: a webhook in the WooCommerce settings
How orders arriveThe plugin posts each paid order to the ROASaurus orders APIWooCommerce posts Order updated; optional REST API check every 5 minutes
Tracking scriptLoaded by the plugin on every pageYou add it, for example with the WPCode plugin or in your theme
Visitor id and click cookies on the orderYes, saved at checkout (classic and block checkout)No
Browser purchase on the thank-you pageYes, with the same event id as the server eventNo
Thank-you page matchingYesNo
Both connections send every paid order. Only the plugin links each order to its visitor at checkout.

You can use both at once. The plugin saves the visitor id on the order as order meta data, and the webhook payload carries it along. ROASaurus stores each order once, by its WooCommerce order id, so the plugin and the webhook never create two purchases. The plugin also declares support for WooCommerce's High-Performance Order Storage.

How is a WooCommerce order matched to the ad click?

An ad platform can only credit a purchase to an ad when it can connect the two. ROASaurus does this by linking the order to the visitor who clicked the ad, and that visitor carries the click ids (such as fbclid and ttclid) and UTM parameters from the landing. It tries these methods in order and stops at the first one that works:

  1. The visitor id saved on the order. Only with the plugin. This is an exact link.
  2. The browser purchase on the thank-you page, which carries the same order id. Only with the plugin.
  3. A hashed email the visitor gave earlier on your site, for example in a Klaviyo, Attentive or Wisepops popup form, or through an Identify call.
  4. The same IP address and browser, seen from 3 hours before to 15 minutes after the order, but only when exactly one visitor fits. On shared networks, such as offices and mobile carriers, several visitors often share one IP address, and then ROASaurus does not guess.

ROASaurus waits briefly before it sends each purchase, so the thank-you page event can arrive first. If the order is still unmatched, it tries again at send time. The Orders page shows the result per order in the Matched by column. Orders linked by the plugin's visitor id show cart, the same label Shopify orders get.

Sent to Meta for order 1042Matched (plugin)Not matched (webhooks only)
Event id order-1042YesYes
Hashed email, phone, name and addressYesYes
IP address and browser of the orderYesYes
Meta click id and browser id (fbc, fbp)YesNo
Hashed visitor id (external_id)YesNo
The ad click in ROASaurus attributionCampaign and ad of the clickShown as direct or unknown
An unmatched order still reaches Meta with the order data. A matched order adds the click identifiers that Meta uses to credit the ad.

Those click identifiers raise Meta's match rate for the event. Event Match Quality explains how Meta scores them.

Each store in ROASaurus has the setting Respect visitor consent, which is on by default. On WooCommerce, the ROASaurus script reads the visitor's choice from the WP Consent API, which consent plugins such as Complianz and CookieYes fill in. It also reads Cookiebot, OneTrust, IAB TCF banners and Google consent mode. Until the visitor accepts marketing cookies, the script sets no visitor id and loads no browser pixels.

When a visitor declines, the script sets no visitor id, keeps no click ids and fires no browser pixels, and the plugin stores no tracking cookies on the order. The paid order is still sent from the server to your connected ad platforms with hashed customer data from the order and the order's IP address and browser. If your legal advice says purchase events also need prior consent, contact ROASaurus before you switch on server-side purchases. The consent help page has the details, and the post on Consent Mode v2 and GDPR covers the legal background.

How to set up WooCommerce server-side tracking

These are the steps for the plugin route:

  1. Add the store

    In ROASaurus, go to Add a store, pick WooCommerce and enter the domain your customers visit.

  2. Create an API key

    Open Store settings and, under Orders API, click Create API key. Copy the key right away: it is shown only once, next to your store key. The endpoint is the address in front of /api/v1/orders on that page.

  3. Install the plugin

    Download the plugin and upload the zip in WordPress under Plugins › Add New Plugin › Upload Plugin, then activate it.

  4. Enter the keys

    Under WooCommerce › ROASaurus, enter the endpoint, the store key and the API key, and save.

  5. Connect your ad platforms

    On Tracking & platforms, use Connect with Facebook or Add pixel for Meta, TikTok and the others. Tick the option to also load the browser pixel, so the thank-you page purchase is deduplicated with the server event.

  6. Set up consent and test

    Block the script in your consent tool until the visitor accepts marketing cookies, then place a test order.

Without the plugin, add the script tag from Tracking & platforms to every page, then create the webhook. The Connection tab of your store shows your webhook URL. Keep it private: anyone with the URL can send orders to your store.

Webhook settings
WooCommerce › Settings › Advanced › Webhooks › Add webhook

Status        Active
Topic         Order updated
Delivery URL  (your webhook URL from the Connection tab)
Secret        (a secret of your choice; paste the same one in ROASaurus)
API version   WP REST API Integration v3

For the backup, create a key under WooCommerce › Settings › Advanced › REST API with read access. Paste the consumer key and secret on the Connection tab, save, and press Test connection. Fetch orders now pulls recent paid orders straight away. The WooCommerce integration page lists every option in one place.

How do you test WooCommerce server-side tracking?

Test the browser side first, then place an order and follow it to the ad platforms.

  • Open your shop with ?roasaurus=connected in the address. An alert confirms that the script runs. With ?roasaurus=debug, the script logs what it sends to the browser console.
  • In the Event log, under Collected events, page views should show a visitor id.
  • Place a test order. Cash on delivery is the quickest, because the order is processing straight away.
  • On the Connection tab, Last order received shows the time of the latest order.
  • In the Event log, under Server deliveries, each connected platform gets a line with the status sent and the platform's response.
PageView visitor 3f9c2a1eScript loaded with consent
Purchase order-1042Thank-you page, browser pixels fired
order 1042 processingReceived from the plugin
Meta Purchase sentSame event id, deduplicated
TikTok CompletePayment sentSame event id, deduplicated
Example of a healthy test order with the plugin. With webhooks only, the thank-you page line is missing and that is expected.

To see the event in Meta, paste the code from Events Manager › Test events into the Test event code field of your Meta pixel in ROASaurus. Remove it when you are done, because the code is meant for testing only. If the plugin cannot deliver an order, it adds an order note in WooCommerce that starts with "ROASaurus: order not sent", followed by the error.

Mistakes to avoid

  • Using the topic Order created. Orders paid by redirect are created as pending payment. ROASaurus ignores unpaid orders, and no second "created" message follows when the payment arrives. Use Order updated.
  • A secret that does not match. ROASaurus rejects a delivery whose signature does not match the secret it has. After more than five failures in a row, WooCommerce disables the webhook. Fix the secret, set the webhook back to Active and add the REST API key, so orders from the gap are fetched.
  • Two tools sending the same pixel. If another plugin also sends your Meta or TikTok pixel, it uses its own event ids and the platform counts each sale twice. Switch it off for that pixel. See preventing double counting and duplicate purchase events.
  • Expecting add-to-cart events. On WooCommerce the script tracks page views by itself. Product views and adds to cart are detected automatically on Shopify only. A developer can send them with a tlq track call.
  • Expecting Google Ads conversions. ROASaurus sends Google Ads purchase conversions from the Shopify checkout only. From WooCommerce it sends purchases to Meta, TikTok, Snapchat, Pinterest, Reddit, X, Microsoft Ads, Taboola, LinkedIn and the other ad platforms you connect.
  • Late bank transfers. Meta accepts server events up to 7 days after the event time. The plugin sends the order with the date it was created, so Meta rejects a transfer confirmed more than 7 days after checkout. Orders that arrive by webhook or the REST API use the paid date instead. Also note that the thank-you page fires the browser purchase at checkout, before the transfer is paid. If the payment is confirmed more than 48 hours later, Meta and TikTok cannot merge the browser and server copies, and a transfer that is never paid keeps its browser purchase.

Once orders flow, the attribution reports show which campaigns and ads they came from.

Sources

  1. WooCommerce: Webhooks Documentation
  2. WooCommerce REST API Documentation - WP REST API v3
  3. WooCommerce: Order Statuses Documentation
  4. WooCommerce: Cash on Delivery Documentation
  5. Meta for Developers: Server Event Parameters

In ROASaurus

Keep reading

Ad platforms and webshopsCash on delivery conversion tracking and external checkoutsCash on delivery conversion tracking: why pixels miss COD and external checkout orders, when to send the purchase, and how to handle refused orders.Ad platforms and webshopsCCV Shop conversion tracking: a setup guideCCV Shop conversion tracking: send paid orders to Meta and TikTok with a signed webhook, link them to ad clicks, set up, test and handle late payments.Ad platforms and webshopsGoogle Ads enhanced conversions on ShopifyEnhanced conversions add hashed customer data to Google Ads purchases on Shopify. How they work, how they differ from offline imports, and the setup.
FAQ

Questions, answered

Do I need the ROASaurus plugin for WooCommerce?

No. A WooCommerce webhook is enough to send every paid order. The plugin adds the visitor id and click cookies to each order and a deduplicated browser purchase on the thank-you page, which links orders to ad clicks exactly, so it is recommended.

Which WooCommerce webhook topic should I use?

Order updated, with API version WP REST API Integration v3. ROASaurus ignores orders that are not processing or completed and stores each order only once, so repeated updates do not create extra purchases.

Are cash on delivery orders sent to Meta and TikTok?

Yes. WooCommerce gives cash on delivery orders the status processing when they are placed, and ROASaurus counts processing orders as paid. Bank transfer orders are sent when you move them from on hold to processing.

What is sent when a visitor declines cookies?

The paid order is still sent from the server with hashed customer data and the IP address and browser from the order. The script should not run without consent, so there is no visitor id or click id to link the order to an ad click.

Why did my WooCommerce webhook stop working?

WooCommerce disables a webhook after more than five failed deliveries in a row. Check that the secret in WooCommerce matches the one in ROASaurus, set the webhook back to Active, and add a REST API key so missed orders are fetched every 5 minutes.

Does ROASaurus send Google Ads conversions from WooCommerce?

Not for purchases. Google Ads purchase conversions are sent from the Shopify checkout only. From WooCommerce, ROASaurus sends purchases to Meta, TikTok, Snapchat, Pinterest, Reddit, X, Microsoft Ads, Taboola, LinkedIn and the other ad platforms you connect.

Every sale, traced to the ad that earned it

Server-side tracking, profit and lifetime value in one app. 14-day free trial, no credit card.

Start your free trial →