Skip to content

serverTracker.trackEvent()

Sends one GA4 event via the Measurement Protocol. The required clientId is GA4’s per-browser identifier (read from the _ga cookie) — without it, GA4 has no way to merge the server event into the browser session.

serverTracker.trackEvent(input: ServerEventInput): Promise<void>;
type ServerEventInput = {
name: string;
clientId: string;
params?: Record<string, unknown>;
userData?: UserData;
};
FieldRequiredNotes
nameyesThe GA4 event name.
clientIdyesThe GA4 client ID — the suffix of the _ga cookie value (GA1.1.<clientId>). Forward it from the browser to your server with the request that triggers the event.
paramsnoEvent parameters, forwarded to GA4 unchanged.
userDatanoIdentity fields. The SDK normalizes and hashes the fields Google expects hashed.

Promise<void>. Resolves after the HTTP call completes — success or failure. Failures do not throw.

POSTs to:

https://www.google-analytics.com/mp/collect?measurement_id=<id>&api_secret=<secret>

with body:

{
"client_id": "<clientId>",
"events": [{ "name": "<name>", "params": { ... } }],
"user_data": { ... }
}

The user_data block is omitted entirely if no userData was passed.

This call does not throw on HTTP failures. Without debug: true, failures are silent.

With debug: true:

  • Non-2xx response: [trackbridge] GA4 MP returned <status> <statusText>
  • Network error: [trackbridge] GA4 MP request failed: <error>

GA4’s _ga cookie has the format GA1.1.<clientId>.<timestamp>. The fragment Trackbridge needs is <clientId> — the third dot-separated piece.

function readGa4ClientId(): string | null {
const match = document.cookie.match(/(?:^|;\s*)_ga=([^;]+)/);
if (!match) return null;
const parts = match[1].split('.');
return parts.length >= 4 ? parts.slice(2, 4).join('.') : null;
}

Send it to your server alongside the request:

await fetch('/api/some-server-event', {
method: 'POST',
body: JSON.stringify({ ...payload, ga4ClientId: readGa4ClientId() }),
});
import { serverTracker } from '@/lib/tracker.server';
await serverTracker.trackEvent({
name: 'subscription_renewed',
clientId: payload.ga4ClientId,
params: { value: 9.99, currency: 'USD' },
});