Hybrid mode
Server-side dispatch plus the platform's own browser pixel, both firing the same event with the same stable event_id. The platform deduplicates, you don't double-count, and the platform gets to see its first-party cookies for better attribution.
What it does
For nine of the ten supported channels you can flip a per-channel toggle that loads the platform's own browser pixel (fbq for Meta, ttq for TikTok, pintrk for Pinterest and so on) on top of Beaconry's server-side dispatch. Browser and server send the same event with the same event_id, the platform's own dedup logic merges them into one conversion. You keep the adblocker-resistance of server-side as the floor, and you gain the first-party cookies (fbp, _ttp, li_fat_id) that the browser pixel sets, which lift match-rate by a couple of points.
Trade-off: you ship a few KB of vendor JavaScript to every consenting visitor. Adblockers will still block the pixel for the share of users who run them, so the lift is on the non-blocked share only. Default is OFF for every channel.
How to enable
wp-admin, Beaconry, Tracking tab. Each channel that supports hybrid mode shows a "Browser pixel" toggle directly under its credentials block. Save settings, the next page-load on the frontend already loads the pixel.
How it works (under the hood)
- Inline init config in
BCNR_Tracking. When a hybrid toggle is on, the per-channel pixel ID is passed into theNLData.init({...})call that bootsnl-data.jsin the browser. The keys aremetaPixelId,tiktokPixelId,linkedinPartnerId,microsoftUetTagId,pinterestTagId,redditPixelId,snapchatPixelId,xAdsPixelIdandgoogleAdsConvId. - The browser bundle loads the vendor pixel.
nl-data.jscontains a small loader per channel (each one a dozen lines of the platform's official snippet). Loaders only run when the matching ID is present in the init config and analytics consent has been given. No dynamicscriptinjection unless both gates pass. - Every event carries one shared
event_id. The forwarder generates a UUID4 per browser-originated event, or a deterministicbcnr_purchase_<order_id>for WooCommerce purchases (so a thank-you-page refresh never double-counts). The browser bundle reads that same ID back from the event payload and hands it to the vendor pixel as the platform's documented dedup key. - The platform deduplicates server-side. Each ad platform supports cross-source dedup, but the key name and the position of the argument differ. Beaconry knows the per-vendor quirks and uses the right field every time, see the matrix below.
Per-channel matrix
Each platform has its own dedup field and its own argument position. Beaconry handles all of them, the table is here so you can verify the wire format in DevTools when debugging.
| Channel | Browser dedup key | Notes |
|---|---|---|
| Meta | fbq('track', name, data, { eventID }) | 4th argument, key is eventID (capital ID). |
| TikTok | ttq.track(name, data, { event_id }) | 3rd argument, key is event_id (snake_case, not eventID). |
pintrk('track', name, { event_id }) | 2nd argument carries the dedup key, not a separate options object. | |
rdt('track', name, { conversionId }) | Reddit calls the dedup key conversionId, not event_id. | |
| Snapchat | snaptr('track', name, { event_id }) | Dedup window is 48 hours on (event_id, event_name). |
| Microsoft UET | uetq.push('event', '', { event_id }) | Per-event dedup added by Microsoft in 2024, requires the empty action string. |
lintrk('track', { event_id }) | Per-event dedup added by LinkedIn in 2024. | |
| X Ads | twq('event', name, { conversion_id }) | X calls the dedup key conversion_id, 48-hour window. |
| Google Ads | Audiences-only, gtag with AW-XXX | No per-event dedup, see special case below. |
| GA4 | Not supported | GA4 is server-only with transaction_id dedup on purchase, see special case below. |
Two special cases
Google Ads, Audiences-only
The Google Ads hybrid toggle does not fire per-event browser conversions. It loads gtag.js with only the AW-XXXXXXXXX conversion-id and send_page_view: false, which lets Google Ads build remarketing audiences from your visitors but leaves the actual conversion tracking entirely to Beaconry's server-side broker. There is no event_id dedup involved because there is no browser-side conversion event to dedup against. The trade-off is intentional: customers asked for audience-building without paying the audit-cost of a browser-side conversion path.
GA4, server-only
GA4 has no hybrid toggle. The Measurement Protocol is server-only inside Beaconry, and dedup against any parallel gtag.js install on the same page happens on transaction_id for purchase events, not on event_id. If you already run a GA4 web stream from another plugin, set the same transaction_id there as in your WooCommerce orders and you will not double-count purchases.
Constants for power-users
None. Hybrid toggles are per-channel checkboxes only, settable in the Tracking tab, no wp-config.php override exists or is needed.
Troubleshooting
- "I see double conversions in the platform": open DevTools, Network tab, find one event. Verify the same
event_id(orconversion_id/conversionId, see matrix) appears in the browser pixel request and in the Beaconry server-side payload. If they differ, the dedup key is broken and you will double-count, file a support ticket. If they match and the platform still double-counts, check the platform's own dedup window (Snap and X Ads need both events within 48 hours). - "DevTools shows the pixel loading but no events": the visitor blocked the pixel with an adblocker. The server-side event still went through, you can verify it in the platform's events manager. Hybrid mode does not help adblocker-affected visitors get more match data, but it does not hurt either.
- "I want to disable browser pixels for one specific page": not currently exposed as a setting. Easiest workaround is to add the page to the excluded-pages list on the Dashboard tab, which disables Beaconry entirely on that URL.