Optimizely
Server-side event delivery to Optimizely for experiment tracking, feature flag analytics, and conversion goal measurement via the Event API.
Why route Optimizely through Datafly Signal
- Your numbers stop depending on what the browser allows. Client-side analytics loses every visit where the tag is blocked or the page unloads early. Signal delivers from the server, so Optimizely receives the complete event stream.
- Client IP and user agent are carried in the payload. Both are taken from the original visitor request rather than your server, which is what Optimizely needs to attribute the event to the right session.
- Delivery is batched, rate-limited, and retried. Signal buffers to Kafka, respects the Optimizely rate limit, and retries on 429 or transient failure rather than dropping the event.
- Presets for Retail, SaaS and Media & Publishing. The mapping starts from a working configuration for your vertical instead of a blank field map.
- One consent decision governs every destination. Optimizely is gated by the same consent state as the rest of your stack, so a withdrawal applies everywhere at once.
Prerequisites
An Optimizely Experimentation account (Web Experimentation, Performance Edge or Feature Experimentation) with the events you want to count created in your project and added as metrics to running experiments.
Step 1: Find your Account ID
Go to Settings > Account (or see Optimizely’s “Find IDs for API calls”) and copy the Account ID.
Step 2: Note your event keys and IDs
In your project, open Events. For each event you will send, note its key (API name) and its numeric ID. The ID ties a conversion to your experiment metrics.
Step 3: Make sure the visitor IDs match
Optimizely attributes a conversion to the variations the visitor was bucketed into, by visitor_id. The server-side event must carry the same visitor ID:
- Web Experimentation / Performance Edge: add a collected ID named
optimizely_visitor_idthat reads theoptimizelyEndUserIdcookie. - Feature Experimentation: bucket users with the same user ID you pass to
datafly.identify().
API Endpoint
POST https://logx.optimizely.com/v1/events # default
POST https://eu.logx.optimizely.com/v1/events # EU, approved accounts onlyNo authentication: the request is attributed by account_id. Signal sends X-Optimizely-Strict: true so a body that fails validation returns 400 instead of the default silent 204.
Configuration
| Field | Type | Required | Description |
|---|---|---|---|
account_id | string | Yes | Your Optimizely account ID. |
event_entity_ids | text | No | A JSON object mapping each event key Signal sends to its Optimizely event ID, for example {"purchase": "12345678901"}. An event without an entry is sent with its key only. |
region | select | No | us (default) or eu (EU-hosted ingestion, approved accounts only). |
project_id | string | No | Only for Optimizely Recommendations. |
What Signal sends
Each event is one conversion:
{
"account_id": "1887578053",
"client_name": "Datafly/Signal",
"client_version": "1.0",
"anonymize_ip": true,
"enrich_decisions": true,
"visitors": [{
"visitor_id": "oeu1691234567890r0.123",
"snapshots": [{
"decisions": [],
"events": [{
"entity_id": "1260528912",
"key": "purchase",
"timestamp": 1758500000123,
"uuid": "3f1c2a90-7d4e-4b8a-9c61-2f0e5d7a1b22",
"revenue": 27998,
"tags": { "transaction_id": "ORD-1001", "currency": "GBP", "tax": 46.66 }
}]
}]
}]
}| Field | Source |
|---|---|
visitor_id | The collected optimizely_visitor_id, else the user ID, else the Signal anonymous ID. |
key | The event name. Rename events on the installed integration to match your Optimizely event keys (case-sensitive). |
entity_id | Looked up by key in event_entity_ids. |
timestamp | Event time, epoch milliseconds. |
uuid | The Signal event ID; Optimizely de-duplicates replays by it. |
revenue | On money events (purchase, trial_converted, subscription_started, subscription_renewed, policy_purchased, policy_renewed): the value in minor units (89.99 becomes 8999). |
value | The numeric value of other events that carry one. |
tags | The event’s other documented properties; currency upper-cased. |
enrich_decisions lets Optimizely attach the visitor’s experiment decisions, so no activation event is sent. No personal data is sent.
Presets
| Preset | Events |
|---|---|
| Default | sign_up, generate_lead, add_to_cart, begin_checkout, purchase, trial_started, subscription_started |
| Retail | view_item, add_to_cart, view_cart, begin_checkout, add_payment_info, purchase, add_to_wishlist, sign_up, generate_lead, coupon_applied |
| B2B / SaaS | generate_lead, demo_requested, sign_up, onboarding_completed, trial_started, trial_converted, subscription_started, subscription_upgraded, subscription_cancelled, subscription_renewed, feature_used, invitation_sent |
| Media & Streaming | content_viewed, content_completed, video_played, video_content_completed, sign_up, generate_lead, begin_checkout, purchase, subscription_renewed, subscription_cancelled |
| Insurance | quote_started, get_quote, quote_completed, generate_lead, lead_submitted, begin_checkout, add_payment_info, purchase, policy_purchased, policy_renewed |
Page views are left to the Optimizely snippet.
Consent
Default consent category: analytics.
Verify it’s working
- In the Signal Management UI, open your Optimizely integration and watch Live Events; the Event API answers
204. - In Optimizely, check the experiment Results: conversions appear within a few minutes for visitors who were bucketed into the experiment.
Troubleshooting
| Symptom | Cause | Fix |
|---|---|---|
400 | The body failed validation (strict mode) | Check the delivery error; account_id, visitor_id, timestamp and uuid are required. |
| Conversions not counted | Visitor ID or event mismatch | Collect optimizely_visitor_id (Web) or bucket by the Signal user ID (Feature Experimentation); set the event’s ID in event_entity_ids; match the event key exactly. |
| Revenue off by 100 | Revenue units | Optimizely revenue is in minor units; Signal converts the event value for you. |
| Conversion before the decision | Timestamps | A conversion older than the visitor’s decision is not counted. |
Blueprint
The Optimizely blueprint version is 0.5.0 (not yet tested against a live Optimizely account).
See also
- Convert — alternative experimentation destination.