@luminpdf/node-ga4
v0.4.0
Published
A Node.js GA4 SDK for event tracking via Measurement Protocol API
Readme
@luminpdf/node-ga4
A Node.js Google Analytics 4 (GA4) SDK for event tracking via the Measurement Protocol API. This package provides a simple, type-safe interface for tracking events to GA4 from your server-side applications, supporting both web and app/Firebase streams.
Features
- 🎯 Singleton Pattern: Ensures a single instance across your application
- 🔒 Type-Safe: Full TypeScript support with proper type definitions
- 📊 Event Tracking: Track events to GA4 via Measurement Protocol
- 🌐 Web & App Support: Supports both web streams (measurement_id) and app/Firebase streams (firebase_app_id)
- ✅ Validation: Built-in validation for event names, parameters, and user properties
- 🚀 Batch Support: Track up to 25 events per request
- 🔧 Flexible Configuration: Support for US and EU regions
Installation
npm install @luminpdf/node-ga4or
pnpm add @luminpdf/node-ga4or
yarn add @luminpdf/node-ga4Prerequisites
- Google Analytics 4 property
- API Secret (generated in GA4 Admin > Data Streams > Measurement Protocol API secrets)
- For web streams: Measurement ID (G-XXXXXXXXXX)
- For app/Firebase streams: Firebase App ID
- Node.js 18+ and TypeScript 4.5+
Usage
Initialize the Client (Web Stream)
import { GA4Client } from "@luminpdf/node-ga4";
const ga4Client = GA4Client.create({
apiSecret: "your-api-secret",
measurementId: "G-XXXXXXXXXX",
region: "us",
disableInDevelopment: false,
});Initialize the Client (App/Firebase Stream)
const ga4Client = GA4Client.create({
apiSecret: "your-api-secret",
firebaseAppId: "your-firebase-app-id",
region: "us",
disableInDevelopment: false,
});Track a Single Event (Web Stream)
await ga4Client.trackEvent(
{
eventName: "button_click",
params: {
button_name: "signup",
page: "homepage",
},
},
"client-id-123",
undefined,
"user-123"
);Track a Single Event (App/Firebase Stream)
await ga4Client.trackEvent(
{
eventName: "tutorial_begin",
params: {
session_id: "session-123",
engagement_time_msec: 100,
},
},
undefined,
"app-instance-id-456",
"user-123"
);Track Multiple Events (Batch)
await ga4Client.trackEvents({
client_id: "client-id-123",
user_id: "user-123",
events: [
{
name: "page_view",
params: {
page_path: "/home",
page_title: "Home",
},
},
{
name: "button_click",
params: {
button_name: "signup",
},
},
],
});Track Events with User Properties
await ga4Client.trackEvents({
client_id: "client-id-123",
user_id: "user-123",
events: [
{
name: "purchase",
params: {
transaction_id: "T12345",
value: 99.99,
currency: "USD",
},
},
],
user_properties: {
customer_tier: {
value: "PREMIUM",
},
subscription_status: "active",
},
});Track Events with Location and Device Info
await ga4Client.trackEvents({
client_id: "client-id-123",
events: [
{
name: "page_view",
params: {
page_path: "/products",
},
},
],
user_location: {
city: "Mountain View",
region_id: "US-CA",
country_id: "US",
},
device: {
category: "mobile",
language: "en",
operating_system: "iOS",
operating_system_version: "17.0",
},
});Track Events with Timestamps
const timestampMicros = Date.now() * 1000;
await ga4Client.trackEvents({
client_id: "client-id-123",
timestamp_micros: timestampMicros,
events: [
{
name: "custom_event",
params: {
custom_param: "value",
},
timestamp_micros: timestampMicros,
},
],
});Get Instance After Initialization
import { GA4Client } from "@luminpdf/node-ga4";
const ga4Client = GA4Client.getInstance();Check Configuration
const config = ga4Client.getConfig();
console.log(config.apiSecret);
console.log(config.measurementId);
console.log(config.region);
const isConfigured = ga4Client.isClientConfigured();API Reference
GA4Client.create(config: GA4ClientConfig): GA4Client
Creates and returns a singleton instance of the GA4Client.
Parameters:
config.apiSecret(required): Your GA4 API Secretconfig.measurementId(optional): Measurement ID for web streams (G-XXXXXXXXXX)config.firebaseAppId(optional): Firebase App ID for app/Firebase streamsconfig.region(optional): Region for data collection - "us" or "eu" (default: "us")config.disableInDevelopment(optional): Disable tracking in development (default: false)
Note: You must provide either measurementId (for web) or firebaseAppId (for app), but not both.
GA4Client.getInstance(): GA4Client
Returns the existing singleton instance. Throws an error if create() hasn't been called.
trackEvent(options, clientId?, appInstanceId?, userId?): Promise<TrackEventsResponse>
Tracks a single event to GA4.
Parameters:
options.eventName(required): The name of the event (max 40 chars, alphanumeric + underscore, must start with letter)options.params(optional): Event parameters (max 25 params per event)options.timestamp_micros(optional): Event timestamp in microsecondsclientId(optional): Client ID for web streams (auto-generated if not provided)appInstanceId(optional): App instance ID for app/Firebase streams (required for app streams)userId(optional): User ID
trackEvents(request: TrackEventsRequest): Promise<TrackEventsResponse>
Tracks multiple events in a single batch request (max 25 events).
Parameters:
request.client_id(optional): Client ID for web streams (auto-generated if not provided)request.app_instance_id(optional): App instance ID for app/Firebase streams (required for app streams)request.user_id(optional): User IDrequest.events(required): Array of event objects (max 25)request.user_properties(optional): User properties (max 25)request.user_location(optional): User location informationrequest.device(optional): Device informationrequest.timestamp_micros(optional): Request-level timestamprequest.validation_behavior(optional): "ENFORCE_RECOMMENDATIONS" or "RELAXED"
Validation Rules
The SDK automatically validates:
- Event names: Max 40 characters, alphanumeric + underscore, must start with letter
- Parameter names: Max 40 characters, alphanumeric + underscore, must start with letter
- Parameter values: Max 100 characters (standard) or 500 characters (GA4 360)
- User property names: Max 24 characters
- User property values: Max 36 characters
- Events per request: Max 25
- Parameters per event: Max 25
- User properties: Max 25
Limitations
According to the GA4 Measurement Protocol documentation:
- Maximum 25 events per request
- Maximum 25 parameters per event
- Maximum 25 user properties
- Event names: 40 characters or fewer
- Parameter names: 40 characters or fewer
- Parameter values: 100 characters or fewer (standard) or 500 characters (GA4 360)
- User property names: 24 characters or fewer
- User property values: 36 characters or fewer
- Post body must be smaller than 130kB
- Timestamps must be within the last 72 hours
Error Handling
The SDK throws errors if:
apiSecretis not provided- Neither
measurementIdnorfirebaseAppIdis provided - Both
measurementIdandfirebaseAppIdare provided - Client is used before initialization
- Validation rules are violated
- GA4 API calls fail
Always wrap tracking calls in try-catch blocks:
try {
await ga4Client.trackEvent({
eventName: "user_action",
params: { action: "click" },
});
} catch (error) {
console.error("Failed to track event:", error);
}Response Format
All tracking methods return a TrackEventsResponse object:
{
validationMessages?: Array<{
fieldPath: string;
description: string;
validationCode: string;
}>
}Development Mode
When disableInDevelopment is set to true, tracking methods will return early without making API calls.
Regions
- US (default):
www.google-analytics.com - EU:
region1.google-analytics.com
Set the region option to "eu" to collect data in the European Union.
TypeScript Support
Full TypeScript support is included. Import types as needed:
import type {
GA4ClientConfig,
TrackEventOptions,
TrackEventsRequest,
TrackEventsResponse,
EventParams,
UserProperties,
} from "@luminpdf/node-ga4";License
ISC
