In a modern OpenCart setup, events like purchase
, add_to_cart
, and view_item
are sent to multiple platforms—GA4, Meta (Facebook) Conversions API, and TikTok Events API. Without proper deduplication, you’ll face:
- Over-reported conversions
- Skewed attribution
- Broken ROAS metrics
🎯 Platforms Covered
Platform | Deduplication Key |
---|---|
GA4 | Automatic w/ event_id |
Meta CAPI | event_id (critical) |
TikTok CAPI | event_id (optional but preferred) |
🧰 Prerequisites
- OpenCart v3.x or v4.x
- Web GTM + Server GTM (for Meta/TikTok CAPI)
- GA4 Configured via GTM
- Meta Pixel + CAPI
- TikTok Pixel + Events API setup
- Consent Management (optional)
📦 Step 1: Generate & Push a UUID for Deduplication
In your OpenCart success.twig
(on purchase confirmation):
Add This Script to Push event_id
:
<script>
(function() {
function uuidv4() {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
var r = Math.random() * 16 | 0,
v = c === 'x' ? r : (r & 0x3 | 0x8);
return v.toString(16);
});
}
const eventID = uuidv4();
window.dataLayer = window.dataLayer || [];
dataLayer.push({
event: 'purchase',
event_id: eventID,
transaction_id: '{{ order_id }}',
value: {{ total }},
currency: '{{ currency }}',
items: [/* product loop data here */]
});
// Store event ID in a cookie or localStorage for server use
localStorage.setItem('event_id_purchase', eventID);
})();
</script>
✅
event_id
is generated once and used across GA4, Meta Pixel, and TikTok tracking layers.
🧪 Step 2: GA4 Tag with event_id
for Purchase
In GTM:
- Event:
purchase
- Add custom parameter:
- Name:
event_id
- Value:
{{DLV - event_id}}
(Create a Data Layer Variable)
- Name:
GA4 automatically supports event_id
deduplication.
🔗 Step 3: Meta Pixel + Meta CAPI with Deduplication
A. Meta Pixel Tag (Client-side)
- Event:
Purchase
- Parameter:
eventID
:{{DLV - event_id}}
Make sure you are explicitly sending
eventID
to Pixel.
B. Meta CAPI (Server-side GTM)
Use a GA4 → Server → Meta CAPI flow.
- Create Meta CAPI tag in Server GTM
- In the request template:
{ "event_name": "Purchase", "event_time": {{Timestamp}}, "event_id": {{event_id}}, "user_data": { "em": {{hashed_email}}, "ph": {{hashed_phone}} }, "custom_data": { "value": {{value}}, "currency": "{{currency}}" } }
- Retrieve
event_id
from client viaevent_id_purchase
in cookies or HTTP header.
⚠️ Must match exact value from the client for deduplication to work.
🎯 Step 4: TikTok CAPI Deduplication
TikTok doesn’t require event_id
strictly, but recommends it for de-duping against pixel events.
A. TikTok Pixel (Client-Side)
- Fire
Purchase
event - Pass
event_id
:{{DLV - event_id}}
into advanced matching
B. TikTok Events API (Server-Side)
In Server GTM or middleware, include event_id
:
{
"event": "Purchase",
"timestamp": "{{Timestamp}}",
"event_id": "{{event_id}}",
"properties": {
"pixel_code": "YOUR_PIXEL_ID",
"user": {
"email": "{{hashed_email}}"
},
"contents": [...],
"currency": "USD",
"value": 200
}
}
Use a lookup variable or cookie to extract event_id
on the server.
🧰 Step 5: Server-Side Retrieval of event_id
Option A: Via Client Cookie → Request Header
Client JS:
document.cookie = "event_id_purchase=" + eventID + "; path=/";
In Server GTM:
- Use
{{Cookie - event_id_purchase}}
Option B: Via x-event-id
Header
Send event_id
using a custom request header in fetch/XHR if your OpenCart has custom integrations.
📊 Step 6: Reporting Use Cases
Report Type | Platform | Metric Example |
---|---|---|
Deduped Purchase Events | Meta Ads | Events matched = 100%, Deduplicated = 50% |
Conversion Matching | TikTok Ads | event_id match status in TikTok Manager |
GA4 Attribution | GA4 | Clean funnel tracking by event ID |
🔐 Consent Integration (Optional)
Wrap deduplication script in consent check:
if (window.Cookiebot && Cookiebot.consents.given.analytics) {
// execute uuid generation + dataLayer.push
}
Or set server-side triggers to only fire with consent=true.
🧠 Pro Tips
- Always log
event_id
with order data in your backend DB for reconciliation - Use the same timestamp granularity (epoch seconds) across systems
- Avoid multiple
event_id
generations for the same action