When managing multi-channel paid campaigns on Google Ads and Facebook Ads, consistent event tracking is essential for unified attribution. However, tracking platforms work in silos, and events like purchase, lead, or add_to_cart can fire with different payloads or timing.
๐งฐ Prerequisites
| Component | Details |
|---|---|
| GTM Web + Server | Web (frontend) + Server container setup |
| Facebook Pixel + CAPI | Connected to Meta Events Manager |
| Google Ads | Conversion ID and Label available |
| OpenCart Website | E-commerce frontend |
| Consent Management | Optional but highly recommended |
๐ฏ Key Goals
- Receive frontend browser events in Server GTM
- Generate a shared
event_idfor deduplication - Forward enriched payloads to both Google Ads CAPI & Meta CAPI
- Add hashed PII and marketing metadata
โ๏ธ Step 1: Client-Side โ Generate UUID & Push Event to GTM Server
In your OpenCart confirmation page (success.twig):
<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 }}',
email: '{{ email | lower | sha256 }}', // Optional
phone: '{{ phone | sha256 }}' // Optional
});
localStorage.setItem('event_id_purchase', eventID);
})();
</script>
โ
This ensures all platforms receive a consistent event_id.
๐งฉ Step 2: GTM Web โ GA4 & Server-Side GA4 Proxy
GA4 Purchase Tag in Web GTM:
- Event:
purchase - Parameters:
transaction_id,value,currency,event_id
Trigger: Custom Event = purchase
Also fire a Custom HTTP Request Tag to send data to Server GTM:
https://gtm.YOURDOMAIN.com/collect?event_id={{DLV - event_id}}&value={{DLV - value}}¤cy={{DLV - currency}}&email={{DLV - email}}&phone={{DLV - phone}}&transaction_id={{DLV - transaction_id}}
๐ ๏ธ Step 3: Server GTM โ Event Router Setup
A. Create a Custom Client
In GTM Server container:
- Name:
OpenCart Client - Listen to
collectendpoint - Parse query string or request body
- Set
event_name=purchase
Output event data to downstream tags.
๐ Step 4: Forward to Meta CAPI & Google Ads in Server GTM
A. Meta Conversions API Tag
In Server GTM:
- Event Name:
Purchase - Fields:
event_id: from requestevent_time:{{Timestamp}}user_data: hashedemail,phonecustom_data:value,currency,transaction_id
Example Payload:
{
"event_name": "Purchase",
"event_time": {{Timestamp}},
"event_id": {{event_id}},
"user_data": {
"em": {{hashed_email}},
"ph": {{hashed_phone}}
},
"custom_data": {
"value": {{value}},
"currency": "{{currency}}",
"transaction_id": "{{transaction_id}}"
}
}
B. Google Ads Enhanced Conversions Tag (Server-Side)
Use the native Google Ads Conversion Tag in Server GTM or send via HTTP Request.
Fields:
- Conversion ID:
AW-XXXXXXX - Conversion Label:
XXXXXX - Email, Phone, etc. (Hashed)
- Value, Currency, Transaction ID
- Event Time
Use deduplication via event_id in Enhanced Conversions field or match key.
๐ Step 5: Consent Filtering (Optional)
In both Web & Server GTM, use Consent Initialization triggers and enable Tag Consent Settings:
- Mark tags as
requires marketing consent - Fire only if consent is granted (via Cookiebot, OneTrust, etc.)
๐งช Step 6: QA & Testing
| Tool | Use Case |
|---|---|
| GTM Preview Mode | Ensure event_id & HTTP tag triggers |
| GA4 DebugView | Confirm deduped event in analytics |
| Meta Events Manager | Verify Purchase event & deduplication |
| Google Ads | Check Enhanced Conversions status |
| Server GTM Logs | Inspect payloads, headers, status codes |
๐ Use Cases
| Insight | Platform | Use Case |
|---|---|---|
| Compare Meta vs Ads attribution | Meta & Google Ads | See which ad drove purchase |
| Audience building by platform | GA4 Audiences | Build audiences only from CAPI buyers |
| Event integrity reporting | Looker Studio | Confirm same event_id across channels |
๐ง Pro Tips
- Always log
event_id+ timestamp in order table for debugging - Add retry logic or webhook fallback for failed server events
- Track client vs server events side-by-side in BigQuery for auditing
