Semantic helpers
The five common ecommerce / acquisition events have dedicated methods. Each takes typed input (with items typed as TrackbridgeItem[] instead of an untyped params blob), fires the right combination of Ads conversion + GA4 event, and shares one transactionId across both destinations for dedup.
You can keep using trackConversion and trackEvent directly. The helpers exist because most calls follow the same five shapes, and the typed surface catches mistakes (wrong field names, missing required fields) at compile time instead of at Google’s API boundary.
The five helpers
Section titled “The five helpers”| Method | GA4 event | Ads behavior |
|---|---|---|
trackPurchase | purchase | Fires Ads when conversionLabels.purchase is set. transactionId required. |
trackBeginCheckout | begin_checkout | Fires Ads when conversionLabels.beginCheckout is set. transactionId optional. |
trackAddToCart | add_to_cart | Fires Ads when conversionLabels.addToCart is set. transactionId optional. |
trackSignUp | sign_up | Fires Ads when conversionLabels.signUp is set. transactionId optional. |
trackRefund | refund | GA4 only. Refund Ads adjustments are out of scope in v1. |
All five exist on both browser and server with symmetric signatures. The server-side input requires clientId (the SDK can’t read the GA4 _ga cookie on the server); the browser side does not.
Opting in to Ads dual-send per helper
Section titled “Opting in to Ads dual-send per helper”Each helper looks up its own key in the conversionLabels config you pass to createBrowserTracker / createServerTracker. Set the key → the helper fires the matching Ads conversion alongside the GA4 event. Omit the key → the helper fires GA4 only.
const tracker = createBrowserTracker({ adsConversionId: 'AW-XXXXXXXXX', ga4MeasurementId: 'G-XXXXXXXXXX', conversionLabels: { purchase: 'abc123', // ← purchase is dual-send beginCheckout: 'def456', // ← so is begin_checkout // addToCart, signUp omitted → GA4 only },});refund is intentionally absent from the conversionLabels shape — Ads refund adjustments use a different API endpoint (uploadConversionAdjustments) that the SDK doesn’t implement in v1.
The TrackbridgeItem type
Section titled “The TrackbridgeItem type”GA4’s ecommerce items[] array is typed as TrackbridgeItem[] so you don’t have to remember which fields are camelCase, snake_case, or whether quantity is a number or a string. The SDK converts to GA4’s snake_case shape (item_id, item_name, …) at serialization time, identically on both runtimes.
import type { TrackbridgeItem } from '@trackbridge/sdk/browser';// (or @trackbridge/sdk/server, or @trackbridge/sdk/core — same type)
const items: TrackbridgeItem[] = [ { itemId: 'sku-1234', itemName: 'Espresso Tamper', price: 39.0, quantity: 1, itemBrand: 'Acme', },];Per GA4’s spec one of itemId / itemName should be set per item; the SDK leaves both optional and trusts the caller.
Server return shape: per-destination outcome
Section titled “Server return shape: per-destination outcome”Each server helper returns a ServerHelperResult describing what happened on each destination separately. Unlike trackConversion (which returns { ads }) and trackEvent (which returns { ga4 }), helpers fan out to both and report on both:
type ServerHelperResult = { ads: HelperSendResult; ga4: HelperSendResult;};
type HelperSendResult = | { ok: true } | { ok: false; error: Error } | { skipped: true; reason: 'no_label_configured' | 'refund_ads_unsupported' };The skipped variant is what a helper reports for a destination it deliberately did not call — for example, trackPurchase returns ads: { skipped: true, reason: 'no_label_configured' } when conversionLabels.purchase is absent. This is observably different from a network failure, and your monitoring should treat it that way.
Same transactionId on both sides
Section titled “Same transactionId on both sides”The dual-send rule that applies to trackConversion applies here too: pass the same transactionId on both browser and server when you fire the same conversion from both. trackPurchase and trackRefund require transactionId; the other three auto-generate (with the standard warning) when omitted, and that auto-generation disables dual-send for that call.
When you call trackPurchase on the browser and on the server with the same order.id, Google sees one Ads conversion (deduped) and one GA4 event per side (the server-side GA4 stitches via clientId).
When to reach past the helpers
Section titled “When to reach past the helpers”The helpers cover the canonical shapes. Drop down to trackConversion / trackEvent when you need:
- A custom event name (
trackEvent({ name: 'newsletter_subscribed', … })). - A conversion that doesn’t map to one of the five canonical events.
- Total control over
paramsfor an exotic GA4 event.
The helpers’ implementations are thin — they assemble the right transaction_id, items, value, currency, and method params and call the underlying trackConversion / trackEvent. Anything they do, you can do directly.
See also
Section titled “See also”tracker.trackPurchase()— browser API reference.serverTracker.trackPurchase()— server API reference.- The dual-send pattern — why dedup matters and how
transactionIdenables it. - Deduplication & transactionId — auto-generation, warning, dual-send rules.