Google Analytics 4 Integration for Feature Experimentation
TL;DR
Integrate Optimizely Feature Experimentation with Google Analytics 4 (GA4) to analyze server-side experiment performance alongside your existing analytics data.
Overview
The GA4 + Feature Experimentation integration enables you to:
Track feature flag decisions in GA4 for server-side and client-side experiments
Segment users by experiment variation in GA4 reports and explorations
Analyze experiment impact using GA4 attribution models and funnel analysis
Combine data from Optimizely experiments with your existing GA4 analytics
Integration Architecture
The diagram below illustrates how data flows from your application through Optimizely to Google Analytics 4:
graph TB
subgraph "Your Application"
A[Client/Server Code]
B[Optimizely SDK]
end
subgraph "Data Pipeline"
C[Decision Notification]
D[Data Layer / Custom Events]
E[Google Tag Manager]
end
subgraph "Google Analytics 4"
F[Event Collection]
G[User Properties]
H[Custom Dimensions]
I[Reports & Explorations]
end
A -->|Initialize & Decide| B
B -->|Triggers| C
C -->|Push| D
D -->|Event| E
E -->|Send| F
F --> G
F --> H
G --> I
H --> IThe diagram below illustrates how data flows from your application through Optimizely to Google Analytics 4:
graph TB
subgraph "Your Application"
A[Client/Server Code]
B[Optimizely SDK]
end
subgraph "Data Pipeline"
C[Decision Notification]
D[Data Layer / Custom Events]
E[Google Tag Manager]
end
subgraph "Google Analytics 4"
F[Event Collection]
G[User Properties]
H[Custom Dimensions]
I[Reports & Explorations]
end
A -->|Initialize & Decide| B
B -->|Triggers| C
C -->|Push| D
D -->|Event| E
E -->|Send| F
F --> G
F --> H
G --> I
H --> IPrerequisites
Before you begin, ensure you have:
An active Optimizely Feature Experimentation account
A GA4 property with gtag.js or Google Tag Manager configured
Optimizely Feature Experimentation SDK installed
Admin access to GA4 (Editor role minimum)
Implementation: With Google Tag Manager
The following sequence diagram shows how the integration works with GTM:
sequenceDiagram
participant App as Your App
participant SDK as Optimizely SDK
participant DL as Data Layer
participant GTM as Google Tag Manager
participant GA4 as Google Analytics 4
App->>SDK: decide() / activate()
SDK->>SDK: Evaluate flag/experiment
SDK->>DL: Push decision event
Note over DL: optimizely-flagKey<br/>optimizely-ruleKey<br/>optimizely-variationKey
DL->>GTM: Trigger on 'optimizely-decision'
GTM->>GA4: Send custom event with parameters
GA4->>GA4: Store experiment data
Note over GA4: Available in reports<br/>& explorationsThe following sequence diagram shows how the integration works with GTM:
sequenceDiagram
participant App as Your App
participant SDK as Optimizely SDK
participant DL as Data Layer
participant GTM as Google Tag Manager
participant GA4 as Google Analytics 4
App->>SDK: decide() / activate()
SDK->>SDK: Evaluate flag/experiment
SDK->>DL: Push decision event
Note over DL: optimizely-flagKey<br/>optimizely-ruleKey<br/>optimizely-variationKey
DL->>GTM: Trigger on 'optimizely-decision'
GTM->>GA4: Send custom event with parameters
GA4->>GA4: Store experiment data
Note over GA4: Available in reports<br/>& explorationsGTM provides better timing control and makes it easier to manage experiment data without deploying code changes.
Step 1: Set Up Notification Listener
Add this code where you initialize the Optimizely SDK:
const { createInstance, enums } = require("@optimizely/optimizely-sdk");
const optimizelyClient = createInstance({
sdkKey: "YOUR_SDK_KEY",
});
optimizelyClient.notificationCenter.addNotificationListener(
enums.NOTIFICATION_TYPES.DECISION,
(decisionNotification) => {
const { type, userId, decisionInfo } = decisionNotification;
if (type !== "flag" || !decisionInfo.decisionEventDispatched) {
return;
}
window.dataLayer = window.dataLayer || [];
window.dataLayer.push({
event: "optimizely-decision",
"optimizely-flagKey": decisionInfo.flagKey,
"optimizely-ruleKey": decisionInfo.ruleKey,
"optimizely-variationKey": decisionInfo.variationKey,
});
}
);Step 2: Create Data Layer Variables in GTM
Create three data layer variables in Google Tag Manager:
Optimizely - flagKey → Data Layer Variable Name:
optimizely-flagKeyOptimizely - ruleKey → Data Layer Variable Name:
optimizely-ruleKeyOptimizely - variationKey → Data Layer Variable Name:
optimizely-variationKey
Step 3: Create GA4 Event Tag
In GTM, create a new GA4 Event tag:
Event Name:
optimizely_decision_fxEvent Parameters:
Flag→{{Optimizely - flagKey}}Rule→{{Optimizely - ruleKey}}Variation→{{Optimizely - variationKey}}
Trigger: Custom Event →
optimizely-decision
GA4 Configuration
Create Custom Dimensions
After events start flowing to GA4, register them as custom dimensions:
GA4 → Admin → Data display → Custom definitions
Click Create custom dimension
Create dimensions for
Flag,Rule, andVariation
Note: Custom dimensions can take 24-48 hours to become available.
Advanced: Server-Side Tracking
For backend experiments, use GA4 Measurement Protocol:
// Node.js example
const https = require("https");
function sendGA4Event(userId, eventName, eventParams) {
const measurementId = "G-XXXXXXXXXX";
const apiSecret = "YOUR_API_SECRET";
const payload = JSON.stringify({
client_id: userId,
events: [{
name: eventName,
params: eventParams,
}],
});
const options = {
hostname: "www.google-analytics.com",
path: `/mp/collect?measurement_id=${measurementId}&api_secret=${apiSecret}`,
method: "POST",
headers: {
"Content-Type": "application/json",
},
};
const req = https.request(options);
req.write(payload);
req.end();
}Next Steps
Test integration in GTM Preview mode
Verify events appear in GA4 Realtime reports
Create segments in GA4 Explorations
Build funnel reports comparing variations
For the complete guide with 25+ code examples, Python/Node.js implementations, troubleshooting, and advanced patterns, see fx-ga4-article.md