Migrating from a gtag-only setup
If your site already fires Google Ads conversions through gtag('event', 'conversion', { ... }) and you’re moving to Trackbridge, the migration is two phases: coexist (Trackbridge runs alongside gtag for a measurement window), then cut over (Trackbridge replaces gtag’s conversion calls). The reason for the two phases is to verify Trackbridge captures everything gtag was capturing before you turn gtag’s calls off — there’s no rolling back a missing day of conversion data.
You don’t have to remove gtag itself. Trackbridge calls gtag — the script still loads, the GA4 events still fire through it. Only the explicit gtag('event', 'conversion', ...) calls in your application code go away.
What you have today
Section titled “What you have today”Most existing setups look like this:
// On the checkout success pagegtag('event', 'conversion', { send_to: 'AW-1234567890/abcDEF1234', transaction_id: order.id, value: order.total, currency: 'USD',});Maybe with user_data for enhanced conversions:
gtag('set', 'user_data', { email_address: order.customer.email, // ...});gtag('event', 'conversion', { /* ... */ });This gets the browser side of dual-send right (you already have a transaction_id). What it’s missing: the server-side fire that catches ad blockers, ITP, and consent denials.
Phase 1: install Trackbridge alongside gtag
Section titled “Phase 1: install Trackbridge alongside gtag”Don’t remove the existing gtag('event', 'conversion', ...) calls yet. Add Trackbridge in parallel.
-
Install both packages and create the trackers per Quick start and Setting up Google Ads OAuth.
-
Map your existing gtag conversion label to a friendly name in
conversionActions:ads: {conversionActions: {purchase: 'customers/1234567890/conversionActions/9876543210',},},(The
'purchase'string is your friendly name; the resource name comes from the Ads UI per Mapping conversion actions.) -
Add
serverTracker.trackConversionto your server-side checkout-success path (Stripe webhook, order-creation API route, etc.):await serverTracker.trackConversion({label: 'purchase',value: order.total,currency: 'USD',transactionId: order.id,gclid: order.gclid,userData: {email: order.customer.email,// ...},});Use the same
transactionId(your order ID) as the existing gtag call. Google will dedup against it. -
Leave the existing gtag call in place. Do not touch the browser side yet.
Now both fire. Google sees two events with the same transaction_id and counts them once.
Phase 1: measure
Section titled “Phase 1: measure”Let this run for at least a week — ideally two — and compare:
- Daily conversion volume in the Ads UI — should be unchanged. Dedup means total count is the same.
- Server-side success rate — your application logs (or
debug: truewarnings) tell you how manyserverTracker.trackConversioncalls succeeded vs failed. Aim for >99% success on a healthy network.
If volume in the Ads UI dropped, something is wrong — most likely transactionId is mismatched, causing Google to count the conversion twice from each side and then your daily-aggregate trends shift. Verify the call shapes match before continuing.
Phase 2: cut over the browser side
Section titled “Phase 2: cut over the browser side”When Phase 1 has been stable for a week, replace your existing gtag conversion call with Trackbridge.
// Remove this:gtag('set', 'user_data', { email_address: order.customer.email, /* ... */ });gtag('event', 'conversion', { send_to: 'AW-1234567890/abcDEF1234', transaction_id: order.id, value: order.total, currency: 'USD',});
// Add this:import { tracker } from '@/lib/tracker.client';
await tracker.trackConversion({ label: 'purchase', value: order.total, currency: 'USD', transactionId: order.id, userData: { email: order.customer.email, // ... },});tracker.trackConversion makes the same gtag('event', 'conversion', ...) call internally — same send_to, same transaction_id, same user_data shape. The difference is that the SDK also picks up gclid/gbraid/wbraid from cookies automatically and normalizes/hashes userData consistently with the server side.
Now you have proper dual-send: SDK on both browser and server, calls on both sides matching, gtag-side captures hopefully all the same conversions it always did, and the server side is your floor.
Things to keep from your old setup
Section titled “Things to keep from your old setup”gtag.jsitself. Don’t remove the script tag. Trackbridge needswindow.gtagto exist; it doesn’t load the library itself.- Other gtag events (
gtag('event', 'add_to_cart', ...), etc.). Trackbridge hastracker.trackEvent()for these, but it’s a thin wrapper — there’s no urgency to migrate them. Migrate when you want shared debug logging and consent state across all your gtag calls; otherwise, leave them. gtag('config', ...)/gtag('consent', ...). Trackbridge does not callgtag('config', ...)orgtag('consent', ...)— those stay in your existing setup (typically a Google Tag Manager container or an inline script in your layout).
Things you can finally delete
Section titled “Things you can finally delete”- Manual SHA-256 hashing of email/phone in your application code. Trackbridge does it. Your old hash code probably uses
toLocaleLowerCaseor trims differently and is silently producing different hashes than Google expects. Remove it. - Manual capturing of
gclidfrom URL params into your own cookie. Trackbridge does this. Remove the bespoke version (clear out the old cookie name on a deploy if you want, but it’ll age out anyway). - Manual click-ID forwarding code that diverges between browser and server. Use
tracker.getClickIdentifiers()once, on the client, when you POST to your backend.
What if you don’t have a transaction_id today
Section titled “What if you don’t have a transaction_id today”Some old gtag setups omit transaction_id. If yours does, Google has been deduping your conversions on best-effort heuristics (typically the gclid + timestamp window). When you migrate, always pass transactionId from day one — don’t try to match the old behavior. The SDK will warn you loudly on every call without it, and the dual-send pattern doesn’t work without it.
This is a real upgrade: your conversion counts will likely change once you start dedup-keying properly. Treat the cutover as a baseline reset.
See also
Section titled “See also”- Quick start — the install path.
- The dual-send pattern — why both sides.
- Deduplication & transactionId — what
transactionIddoes to Google’s matching.