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.
Signature
Section titled “Signature”serverTracker.trackEvent(input: ServerEventInput): Promise<ServerEventResult>;ServerEventInput
Section titled “ServerEventInput”type ServerEventInput = { name: string; clientId: string; params?: Record<string, unknown>; userData?: UserData;};| Field | Required | Notes |
|---|---|---|
name | yes | The GA4 event name. |
clientId | yes | The 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. |
params | no | Event parameters, forwarded to GA4 unchanged. |
userData | no | Identity fields. The SDK normalizes and hashes the fields Google expects hashed. |
Returns
Section titled “Returns”type ServerEventResult = { ga4: SendResult;};
type SendResult = | { ok: true } | { ok: false; error: Error };Resolves after the HTTP call completes. Runtime API failures (network errors, non-2xx responses) do not throw — they’re captured on result.ga4.error. The structured shape leaves room for future destinations (Meta CAPI, TikTok Events API, etc.) without breaking the contract.
Behavior
Section titled “Behavior”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.
Errors and warnings
Section titled “Errors and warnings”Runtime API failures land on result.ga4.error regardless of the debug flag. The debug: true flag only controls whether the same failure is also logged via console.warn:
- Non-2xx response:
[trackbridge] GA4 MP returned <status> <statusText> - Network error:
[trackbridge] GA4 MP request failed: <error>
This call never throws on HTTP failures — inspect the result to surface failures to your own observability pipeline.
Forwarding the clientId from the browser
Section titled “Forwarding the clientId from the browser”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() }),});Example
Section titled “Example”import { serverTracker } from '@/lib/tracker.server';
const result = await serverTracker.trackEvent({ name: 'subscription_renewed', clientId: payload.ga4ClientId, params: { value: 9.99, currency: 'USD' },});
if (!result.ga4.ok) { // Forward to your monitoring; the call did not reach GA4 successfully. reportError(result.ga4.error);}See also
Section titled “See also”tracker.trackEvent()(browser)serverTracker.trackConversion()— for Google Ads conversions, not GA4 events.