π΄ Phase 1 β CoreΒ Β·Β The single most important event. Drives revenue, ROAS, and Google Ads conversions.
purchase β
When to pushβ
On the order confirmation page (/checkout/success, /order/thank-you, etc.), after the order is committed to the database.
β οΈ Exactly once per order. See idempotency.
Complete exampleβ
window.dataLayer.push({ ecommerce: null });
window.dataLayer.push({
event: 'purchase',
ecommerce: {
transaction_id: 'ORD-2026-00123', // REQUIRED, unique
currency: 'EUR',
value: 109.00, // merchandise (excl. shipping/tax)
tax: 18.17,
shipping: 4.95,
coupon: 'SPRING10',
affiliation: 'Biosphere Online Store',
items: [
{
item_id: 'BIO-CRM-001',
item_name: 'Hydrating Day Cream',
item_brand: 'Biosphere',
item_category: 'Skincare',
item_category2: 'Face',
item_variant: '50 ml',
price: 42.00,
quantity: 2,
discount: 0
},
{
item_id: 'BIO-SER-002',
item_name: 'Radiance Serum',
item_brand: 'Biosphere',
item_category: 'Skincare',
item_category2: 'Face',
price: 25.00,
quantity: 1,
discount: 10.00
}
]
},
user_data: {
email: 'jane.doe@example.com',
phone: '+33612345678',
first_name: 'Jane',
last_name: 'Doe',
address: {
street: '12 Lilac Street',
city: 'Paris',
region: 'IDF',
postal_code: '75011',
country: 'FR'
},
external_id: 'user_12345'
}
});
Parametersβ
Event levelβ
| Parameter | Type | Required |
|---|---|---|
transaction_id | string | REQUIRED β unique per order |
currency | string | REQUIRED |
value | number | REQUIRED β merchandise, excl. shipping/tax |
items | array | REQUIRED |
tax | number | recommended |
shipping | number | recommended |
coupon | string | optional |
affiliation | string | optional |
Item levelβ
All standard fields (items). Critical to include:
item_id(must match Meta Catalog)price(after item-level discount)quantitydiscount(if item-level discount applies)
user_data REQUIREDβ
Send everything you have about the customer. The more complete, the better Meta matches (target EMQ β₯ 8) and the more accurate the Google Ads attribution (Enhanced Conversions). See user_data.
Platformsβ
| Platform | Native event | Notes |
|---|---|---|
| GA4 | purchase | Revenue, ROAS, transactions |
| Meta | Purchase | CAPI + Pixel, deduped via event_id, contents for DPA |
| Google Ads | Conversion + Enhanced Conversions | Hashed user_data uploaded |
The transaction_id is sacredβ
Without a unique transaction_id:
- GA4 dedupes badly β revenue inflated on every refresh.
- Meta CAPI counts twice β ROAS/CPM corrupted.
- Google Ads conversion may be rejected.
Rules:
- Unique per order.
- Stable (never regenerated).
- Ideally = customer-facing order number.
- String, max 100 chars.
Amount consistencyβ
value (merchandise) = Ξ£ (item.price Γ item.quantity) - global coupons
total paid = value + tax + shipping
GA4 reports value as revenue. The total paid is reconciled by summing.
Fatal pitfallsβ
- β No
transaction_idor non-unique. - β Push before DB commit β ghost revenue if payment fails async.
- β Re-push on refresh β double counting.
- β
valueincludes shipping/tax β inflated ROAS. - β Cents instead of units (
10900instead of109.00). - β
item_idβ Meta Catalog β DPA audiences broken. - β Pushing without
user_dataβ Meta EMQ ~ 3/10, massive signal loss.