Skip to content

Event Dispatching and Analytics

intermediate

The problem: reliable tracking without performance cost

Section titled “The problem: reliable tracking without performance cost”

Experiments are only useful if you can measure their outcomes. Every time a visitor clicks a button, completes a purchase, or reaches a milestone, that conversion event must reach Optimizely’s analytics backend. But sending an HTTP request on every single event would slow down your application and create a fragile dependency on network availability.

Optimizely solves this by decoupling event capture from event delivery. Events are collected locally, batched together, and dispatched asynchronously. If delivery fails, events are retried. Your application never waits for analytics to respond.

The event pipeline has four stages, shared conceptually by both Feature Experimentation and Web Experimentation:

  1. Capture — Your code signals that something happened (a click, a purchase, a signup).
  2. Enrich — The SDK or snippet attaches context: which experiment the user is in, which variation they saw, user attributes, and a timestamp.
  3. Batch — Multiple events are grouped into a single network payload to reduce HTTP overhead.
  4. Dispatch — The batched payload is sent to Optimizely’s event endpoint via HTTPS POST.

Once events reach Optimizely’s backend, Stats Engine processes them, updates experiment results, and determines statistical significance.

In Feature Experimentation, you explicitly track events in your application code:

// Track a conversion event
optimizelyClient.track('purchase_completed', userId, {
revenue: 4999, // in cents
currency: 'USD'
});

The SDK handles the rest. It attaches the user’s experiment assignments, bundles the event into a batch, and dispatches it asynchronously. Your application code does not block on the network call.

Server-side SDKs batch events to reduce network overhead. The batch processor collects events and flushes them based on two triggers:

  • Batch size — When the queue reaches a configurable number of events (default: 10), the batch is dispatched.
  • Flush interval — When a configurable time period elapses (default: 30 seconds), whatever is in the queue is dispatched regardless of size.

You can tune both parameters at SDK initialization. High-traffic applications benefit from larger batch sizes. Low-traffic applications benefit from shorter flush intervals to avoid stale data.

If a dispatch fails (network timeout, server error), the SDK retries with exponential backoff. Events are not lost on transient failures. However, if your application shuts down before a flush completes, queued events may be lost. Call close() on the SDK during graceful shutdown to flush remaining events.

For environments with specific networking requirements — corporate proxies, custom logging, or compliance constraints — you can replace the default event dispatcher with your own implementation. A custom dispatcher receives the event payload and is responsible for delivering it.

Common use cases for custom dispatchers:

  • Warehouse-native analytics — Route events to your data warehouse (Snowflake, BigQuery, Redshift) instead of or in addition to Optimizely
  • Queue-based delivery — Write events to a message queue (Kafka, SQS) for guaranteed delivery
  • Compliance filtering — Strip or hash PII attributes before events leave your infrastructure

Web Experimentation tracks events differently because it runs in the browser:

  • Automatic tracking — Click goals and pageview goals defined in the Optimizely UI are tracked automatically. The snippet attaches event listeners to matching elements.
  • Custom events — For events that are not simple clicks or pageviews, you use the push API:
// Track a custom conversion event
window.optimizely.push({
type: 'event',
eventName: 'purchase_completed',
tags: {
revenue: 4999,
currency: 'USD'
}
});

The snippet dispatches events using the browser’s navigator.sendBeacon() API when available, falling back to XHR. Beacon is preferred because it reliably delivers data even during page unload — visitors navigating away do not cause lost events.

After events reach Optimizely’s backend, the processing pipeline is identical:

  • Deduplication — Duplicate events (from retries) are identified and collapsed.
  • Attribution — Events are attributed to the correct experiment and variation based on the user context attached at capture time.
  • Aggregation — Raw events are rolled up into metrics: conversion rates, revenue per visitor, and other KPIs.
  • Statistical analysis — Stats Engine applies sequential testing to determine whether observed differences are statistically significant.

Results appear on the experiment results page, typically within minutes of event dispatch.

Both products support revenue tracking by attaching a revenue tag to events. Revenue values should be in the smallest currency unit (cents for USD, pence for GBP). Optimizely aggregates revenue per visitor and calculates statistical significance on revenue metrics just like conversion rates.

Event capacity scales with your Optimizely plan tier:

TierMonthly event capacity
EssentialIncluded allocation per contract
EnhancedHigher allocation with overage pricing
AdvancedSignificantly higher allocation
UltimateCustom allocation with dedicated support

If your application generates high event volume, use batching aggressively and consider filtering low-value events before dispatch. Not every user interaction needs to be an experiment metric.

When events are not appearing in results, check these common causes:

  • SDK not initialized — Events tracked before the SDK finishes initialization are silently dropped.
  • Event key mismatch — The event name in track() must exactly match the event key defined in the Optimizely app.
  • Missing decision — A user who was never bucketed into an experiment will not have their events attributed to that experiment.
  • Flush timing — Events are batched. Check whether your flush interval is long enough that you are simply waiting for the next batch.
  • Network failures — Inspect outbound requests to logx.optimizely.com to confirm events are being dispatched.