My solution
1
Create variables in GTM for the necessary tracking identifiers: GA4 Client ID (client_id), Meta Browser ID (_fbp), Meta Click ID (_fbc), and Google Ads Click ID (gclid).
2
Create tags and triggers in GTM to track the visitor engagements you listed: «Page Views», «Scroll Depth», «Time on Page», «Buy Tickets» clicks, etc.
3
When the Eventbrite Checkout Widget is rendered, it sends an undocumented message containing Eventbrite's Event ID from its iframe to the parent window:
window.parent.postMessage({
messageName: 'widgetRenderComplete',
eventId: '1611364838609'
}, 'https://crawlwith.us/');
3.1
This undocumented message is visible both in the DOM of the widget's iframe and in the widget's source code: eventbrite.com/static/widgets/eb_widgets.js
3.2
Eventbrite's Event ID must be pushed to the Data Layer (to be sent to GTM):
window.addEventListener('message', e => {
if ('widgetRenderComplete' === e.data?.messageName) {
window.dataLayer = window.dataLayer || [];
window.dataLayer.push({
'event': 'eb_checkout_started',
'eventbrite_event_id': e.data.eventId
});
}
});
3.3
In GTM, create a «Custom Event» trigger for the eb_checkout_started event.
The tags fired by this trigger must send the begin_checkout event to GA4 and the InitiateCheckout event to Meta: for both events, it is necessary to pass eventbrite_event_id in the platform-specific parameters (as item_id in the items array for GA4 and in the content_ids array for Meta).
4
Similarly to §3, when the visitor closes the widget, the widget sends an undocumented message to the parent window:
window.parent.postMessage({
messageName: 'widgetModalClose',
eventId: '1611364838609'
}, 'https://crawlwith.us/');
Processing this event similarly to §3 makes it possible to track abandoned checkouts, provided that the order has not been completed.
5
When a visitor buys a ticket, the widget calls the onOrderComplete callback: eventbrite.com/platform/docs/embedded-checkout
The documentation at the link above does not document the parameters of this callback, but the source code of eb_widgets.js (§3.1) shows that the callback receives an object containing Eventbrite's Order ID:
e.userConfig.onOrderComplete({orderId:n})
Eventbrite's Order ID must be pushed to the Data Layer (as in §3.2):
window.dataLayer.push({
'event': 'eb_order_success_browser',
'eventbrite_order_id': orderData.orderId
});
6
A tag in GTM fired by the eb_order_success_browser trigger must collect the data from §1 and §5 into a single object and send it to your server.
7
In the Eventbrite Account Settings, it is necessary to configure a webhook for the «Order» → «Placed» action: eventbrite.com/platform/docs/webhooks
This webhook makes a POST request to your server, passing a payload with an API URL containing Eventbrite's Order ID.
Next, after a short delay, using this Order ID and the expand parameter, your server must request full information about the order: eventbrite.com/platform/api#/reference/order/retrieve/retrieve-order-by-id
8
Next, your server must combine the information from §6 and §7.2 using this Order ID.
8.1
Then, this information must be passed to Meta, GA4, and Google Ads using their APIs:
Meta Conversions API:
GA4 Measurement Protocol:
Google Ads API (Offline Conversions and Enhanced Conversions):
developers.google.com/google-ads/api/docs/conversions/upload-offline
8.2
For deduplication, pass Eventbrite's Order ID as event_id for Meta, as transaction_id for GA4, and as order_id for Google Ads.
8.3
For session attribution in GA4, pass the GA4 Client ID (§1) as client_id and the GA4 Session ID as session_id.
8.4
For attribution in Google Ads, use Offline Conversions (passing the Google Ads Click ID from §1) and Enhanced Conversions (passing the hashed buyer data from §7).