Mapping conversion actions
Every conversion in Google Ads has two identifiers, used by two different products:
| Identifier | Used by | Example |
|---|---|---|
| gtag conversion label | Browser-side gtag('event', 'conversion', { send_to: ... }) | abcDEF1234 |
| Ads API resource name | Server-side Ads API uploadClickConversions | customers/1234567890/conversionActions/9876543210 |
These describe the same conversion in the Ads UI. They look completely different in code. Mixing them up — sending a resource name to gtag, or a label to the Ads API — fails on both sides with confusing errors.
Trackbridge keeps them in their lanes. The conversionActions map on createServerTracker is the bridge.
The map
Section titled “The map”import { createServerTracker } from '@trackbridge/server';
createServerTracker({ // ... ads: { // ... conversionActions: { purchase: 'customers/1234567890/conversionActions/9876543210', signup: 'customers/1234567890/conversionActions/1122334455', lead: 'customers/1234567890/conversionActions/3344556677', }, },});Keys are your friendly labels — strings you choose for your own readability. The same label you pass as label to trackConversion. They are not the gtag conversion label; they are not visible to Google.
Values are Ads API resource names in the format customers/{customerId}/conversionActions/{actionId}.
When you call:
await serverTracker.trackConversion({ label: 'purchase', // ...});The server tracker looks up 'purchase' in conversionActions, gets 'customers/1234567890/conversionActions/9876543210', and sends that to the Ads API as the conversionAction field of the upload request.
The browser side
Section titled “The browser side”The browser side does not use conversionActions. It uses the friendly label directly to construct the gtag send_to:
await tracker.trackConversion({ label: 'purchase', // ...});
// Internally becomes:gtag('event', 'conversion', { send_to: 'AW-1234567890/purchase', // ← `${adsConversionId}/${label}` // ...});But wait — 'purchase' isn’t a valid gtag conversion label. Google’s gtag labels are short opaque strings like abcDEF1234.
This is the part that needs deliberate setup in the Ads UI: name your conversion action with the same string you’ll use in code. When you create the conversion action in Ads UI → Tools & Settings → Measurement → Conversions, give it a clear name (e.g. “Purchase”), and configure its conversion label to match — or, more commonly, give the Ads action a normal name and configure the gtag to fire on a friendly identifier you choose.
The cleanest setup is to use the same string in three places:
- The key in
conversionActionsmap:'purchase'. - The
labelyou pass to bothtracker.trackConversionandserverTracker.trackConversion:'purchase'. - The gtag label configured in the Ads UI for that conversion action:
'purchase'.
When all three match, your code stays readable, the dual-send pairs up correctly, and Google sees consistent identifiers from both sides.
Finding the resource name
Section titled “Finding the resource name”In the Ads UI:
- Tools & Settings → Measurement → Conversions.
- Click into the conversion action you want to map.
- Open the Tag setup view, then choose Use Google Tag Manager or Use the Google tag — both expose the resource name (look for “Conversion ID” + “Conversion label” or the API resource path, depending on UI version).
If you can’t find it in the UI, query the Ads API directly:
curl -X POST \ -H "Authorization: Bearer <accessToken>" \ -H "developer-token: <devToken>" \ -H "Content-Type: application/json" \ https://googleads.googleapis.com/v17/customers/1234567890/googleAds:searchStream \ -d '{ "query": "SELECT conversion_action.id, conversion_action.name FROM conversion_action" }'The resource name is customers/1234567890/conversionActions/<conversion_action.id>.
Adding a new conversion type
Section titled “Adding a new conversion type”When you ship a new event (say, “lead”):
-
Create the conversion action in Ads UI. Name it
Lead. Give it a friendly identifier you’ll use in code —lead. -
Find its resource name (or API ID).
-
Add to
conversionActions:conversionActions: {purchase: 'customers/1234567890/conversionActions/9876543210',signup: 'customers/1234567890/conversionActions/1122334455',lead: 'customers/1234567890/conversionActions/3344556677', // new}, -
Call
tracker.trackConversion({ label: 'lead', /* ... */ })andserverTracker.trackConversion({ label: 'lead', /* ... */ })from your application code.
If you forget step 3, the server side throws at call time:
Error: [trackbridge] no conversionAction configured for label "lead" — add it to ads.conversionActions on createServerTrackerWhat happens if you mix them up
Section titled “What happens if you mix them up”- Resource name passed as gtag label: the browser-side
send_tobecomesAW-1234567890/customers/.../conversionActions/..., which Ads doesn’t recognize. The browser fire is silently lost (or, withdebug: true, gtag may emit its own warning). - Friendly label passed to Ads API: the server-side Ads API rejects with
INVALID_CONVERSION_ACTION_RESOURCE_NAME. Withdebug: true, you’ll see the rejection in your logs.
The map prevents both, as long as you put the right string in the right slot.
See also
Section titled “See also”serverTracker.trackConversion()— where the lookup happens.- Setting up Google Ads OAuth — Step 5 covers finding resource names.
trackbridge-conversionsskill — interactive walkthrough.