Skip to content

Architecture & Cache-Safe Deduplication

The Problem with Traditional Server-Side Tracking

Section titled “The Problem with Traditional Server-Side Tracking”

On a typical WordPress site using full-page caching:

  1. Static HTML Caching: The server renders the HTML once and stores it on disk or in memory (WP Rocket, LiteSpeed, Cloudflare).
  2. ID Collision: If a plugin generates the event_id in PHP during page generation, that single ID is frozen into the cached HTML. Every subsequent visitor receives the exact same event_id.
  3. Lost Conversions: When two different visitors submit a form on the cached page, Meta sees the duplicate event_id and discards the second real conversion as a duplicate.
[ Visitor A ] ──▶ Loads cached page (event_id: "xyz-123") ──▶ Submits Form ──▶ Meta records Lead
[ Visitor B ] ──▶ Loads cached page (event_id: "xyz-123") ──▶ Submits Form ──▶ Meta DISCARDS (Duplicate) ❌

SignalRelay Solution: Client-Generated event_id

Section titled “SignalRelay Solution: Client-Generated event_id”

SignalRelay decouples ID generation from server page rendering:

[ Visitor A ] ──▶ JS generates unique event_id "sr_a98f..." ──▶ Server dispatches CAPI with "sr_a98f..." ──▶ Meta Accepts ✅
[ Visitor B ] ──▶ JS generates unique event_id "sr_b44c..." ──▶ Server dispatches CAPI with "sr_b44c..." ──▶ Meta Accepts ✅
  1. Client-Side Generation: The lightweight tracking.js script generates a unique cryptographic UUID v4 for each event at the exact instant an action occurs.
  2. Dual-Channel Dispatch: The same event_id is passed simultaneously to the browser pixel (fbq('track', 'Lead', {...}, {eventID: id})) and to the local SignalRelay REST endpoint (/wp-json/signalrelay/v1/event).
  3. Server-Side Delivery: Your WordPress server receives the payload, verifies user consent, hashes customer data with SHA-256, and queues the conversion. A background job then delivers it to the official API (see Delivery Queue).
  4. Accurate Deduplication: Meta merges both signals using the matching event_id, maximizing your Event Match Quality (EMQ) without double counting.

The visitor never waits for an advertising platform. Each conversion goes into an Action Scheduler queue on your server and a background job sends it, normally within a minute. A delivery that fails in a way a retry can fix (a network error, or a temporary platform error such as a 5xx or a rate limit) is retried up to three more times over roughly 20 minutes.

The activity log only lists events that have already settled, so a stuck queue would look like a quiet site. SignalRelay therefore warns you, in the Overview tab of the dashboard and in Tools → Site Health, when:

  • a conversion has been waiting in the queue for more than 10 minutes, or
  • conversions failed to deliver permanently in the last 7 days. A failed delivery is not retried, and the error is listed under Tools → Scheduled Actions.

The usual cause of a waiting queue is a site that does not run WordPress’s scheduled tasks. If DISABLE_WP_CRON is set in wp-config.php, remove it or add a server cron job that requests wp-cron.php every minute. Nothing is lost while the queue waits: the conversions are sent as soon as it runs again.