> Part of the walkerOS documentation. Project overview and full index: <https://www.walkeros.io/llms.txt>

# Optimizely

<!-- -->

[Web](#)[ ](https://github.com/elbwalker/walkerOS/tree/main/packages/web/destinations/optimizely)

<!-- -->

[Source code](https://github.com/elbwalker/walkerOS/tree/main/packages/web/destinations/optimizely)[ ](https://www.npmjs.com/package/@walkeros/web-destination-optimizely)

<!-- -->

[Package](https://www.npmjs.com/package/@walkeros/web-destination-optimizely)

<!-- -->

Beta

[Optimizely Feature Experimentation](https://www.optimizely.com/products/experiment/feature-experimentation/) runs A/B tests and feature rollouts. This destination forwards walkerOS events to Optimizely as conversion events via the official [`@optimizely/optimizely-sdk`](https://www.npmjs.com/package/@optimizely/optimizely-sdk) v6 modular API, calling `userContext.trackEvent(eventKey, eventTags)` with optional revenue/value tags and user attributes.

<!-- -->

Where this fits

Optimizely is a **web destination** in the walkerOS flow:

## Installation[​](#installation "Direct link to Installation")

```
npm install @walkeros/web-destination-optimizely
```

* Integrated
* Bundled

```
import { startFlow } from '@walkeros/collector';
import { destinationOptimizely } from '@walkeros/web-destination-optimizely';

await startFlow({
  destinations: {
    optimizely: {
      code: destinationOptimizely,
      config: {
        settings: {
          sdkKey: 'YOUR_SDK_KEY',
          userId: 'user.id',
        },
      },
    },
  },
});
```

Add to your `flow.json` destinations:

```
"destinations": {
  "optimizely": {
    "package": "@walkeros/web-destination-optimizely",
    "config": {
      "settings": {
        "sdkKey": "YOUR_SDK_KEY",
        "userId": "user.id"
      }
    }
  }
}
```

[See bundled mode setup](https://www.walkeros.io/docs/getting-started/modes/bundled.md) | [CLI reference](https://www.walkeros.io/docs/apps/cli.md)

## Configuration[​](#configuration "Direct link to Configuration")

This <!-- -->destination<!-- --> uses the standard <!-- -->destination<!-- --> config wrapper (consent, data, env, id, ...). For the shared fields see [destination<!-- --> configuration](https://www.walkeros.io/docs/destinations.md#configuration). Package-specific fields live under `config.settings` and are listed below.

## Settings[​](#settings "Direct link to Settings")

| Property         | Type      | Description                                                                                                                                     | More |
| ---------------- | --------- | ----------------------------------------------------------------------------------------------------------------------------------------------- | ---- |
| `sdkKey*`        | `string`  | Your Optimizely Feature Experimentation SDK key. Find it in your Optimizely project under Settings > Environments.                              |      |
| `userId`         | `any`     | walkerOS mapping value to resolve userId for experiment bucketing. Example: "user.id" or { key: "user.id", value: "user.device" } for fallback. |      |
| `attributes`     | `any`     | User attributes for audience targeting. Resolves to Record\<string, unknown>. Applied to every event via createUserContext().                   |      |
| `updateInterval` | `integer` | Polling interval for datafile updates in milliseconds. Default: 60000.                                                                          |      |
| `autoUpdate`     | `boolean` | Auto-update datafile via polling. Default: true.                                                                                                |      |
| `batchSize`      | `integer` | Batch event processor: number of events per batch. Default: 10.                                                                                 |      |
| `flushInterval`  | `integer` | Batch event processor: flush interval in milliseconds. Default: 1000.                                                                           |      |
| `skipOdp`        | `boolean` | Skip Optimizely Data Platform (ODP) manager initialization. Default: true. Set to false only if you use ODP.                                    |      |

\* Required fields

## Mapping[​](#mapping "Direct link to Mapping")

Per-event rules under `config.mapping`. For the standard rule fields (consent, condition, data, batch, name, policy) see [mapping](https://www.walkeros.io/docs/mapping.md).

| Property     | Type     | Description                                                                                                                                 | More |
| ------------ | -------- | ------------------------------------------------------------------------------------------------------------------------------------------- | ---- |
| `eventKey`   | `string` | Override event key sent to Optimizely. If omitted, the walkerOS event name is used. Must match an event created in your Optimizely project. |      |
| `revenue`    | `any`    | Revenue mapping. Resolves to an integer in cents (e.g. 7281 = $72.81). Passed as eventTags.revenue to trackEvent().                         |      |
| `value`      | `any`    | Numeric value mapping. Resolves to a float. Passed as eventTags.value to trackEvent().                                                      |      |
| `eventTags`  | `any`    | Additional event tags. Resolves to Record\<string, unknown>. Spread into the eventTags object passed to trackEvent().                       |      |
| `attributes` | `any`    | Per-event user attributes override. Resolves to Record\<string, unknown>. Applied via setAttribute() before this event's trackEvent() call. |      |

## Examples

### Attributes only

A profile update sets Optimizely user attributes without firing a trackEvent for user enrichment.

Event

```
{
  "name": "profile update",
  "data": {
    "plan": "premium",
    "country": "DE"
  },
  "context": {
    "dev": [
      "test",
      1
    ]
  },
  "globals": {
    "lang": "elb"
  },
  "custom": {
    "completely": "random"
  },
  "user": {
    "id": "us3r",
    "device": "c00k13",
    "session": "s3ss10n"
  },
  "nested": [
    {
      "entity": "child",
      "data": {
        "is": "subordinated"
      }
    }
  ],
  "consent": {
    "functional": true
  },
  "id": "fdc94f7bb0478100",
  "trigger": "test",
  "entity": "profile",
  "action": "update",
  "timestamp": 1700000105,
  "timing": 3.14,
  "source": {
    "count": 1,
    "trace": "0a1b2c3d4e5f60718293a4b5c6d7e8f9",
    "type": "collector",
    "schema": "4"
  }
}
```

Mapping

```
{
  "silent": true,
  "settings": {
    "attributes": {
      "map": {
        "plan": "data.plan",
        "country": "data.country"
      }
    }
  }
}
```

Out

```
optimizely.setAttribute("plan", "premium");

optimizely.setAttribute("country", "DE")
```

### Consent revoked

A walker consent command with analytics denied closes the Optimizely client and flushes queued events.

Event

```
{
  "analytics": false
}
```

Out

```
optimizely.close()
```

### Default event

A walker event becomes an Optimizely trackEvent call with the event name and empty eventTags.

Event

```
{
  "name": "page view",
  "data": {
    "domain": "www.example.com",
    "title": "walkerOS documentation",
    "referrer": "https://www.walkeros.io/",
    "search": "?foo=bar",
    "hash": "#hash",
    "id": "/docs/"
  },
  "context": {
    "dev": [
      "test",
      1
    ]
  },
  "globals": {
    "pagegroup": "docs"
  },
  "custom": {
    "completely": "random"
  },
  "user": {
    "id": "us3r",
    "device": "c00k13",
    "session": "s3ss10n"
  },
  "nested": [
    {
      "entity": "child",
      "data": {
        "is": "subordinated"
      }
    }
  ],
  "consent": {
    "functional": true
  },
  "id": "b2274686fc0e3240",
  "trigger": "load",
  "entity": "page",
  "action": "view",
  "timestamp": 1700000100,
  "timing": 3.14,
  "source": {
    "count": 1,
    "trace": "0a1b2c3d4e5f60718293a4b5c6d7e8f9",
    "type": "collector",
    "schema": "4"
  }
}
```

Out

```
optimizely.trackEvent("page view", {})
```

### Mapped event key

A mapping renames the walker event to an Optimizely event key defined in the project.

Event

```
{
  "name": "product view",
  "data": {
    "id": "ers",
    "name": "Everyday Ruck Snack",
    "color": "black",
    "size": "l",
    "price": 420
  },
  "context": {
    "shopping": [
      "detail",
      0
    ]
  },
  "globals": {
    "pagegroup": "shop"
  },
  "custom": {
    "completely": "random"
  },
  "user": {
    "id": "us3r",
    "device": "c00k13",
    "session": "s3ss10n"
  },
  "nested": [],
  "consent": {
    "functional": true
  },
  "id": "77b216af39236edc",
  "trigger": "load",
  "entity": "product",
  "action": "view",
  "timestamp": 1700000101,
  "timing": 3.14,
  "source": {
    "count": 1,
    "trace": "0a1b2c3d4e5f60718293a4b5c6d7e8f9",
    "type": "collector",
    "schema": "4"
  }
}
```

Mapping

```
{
  "name": "product_viewed"
}
```

Out

```
optimizely.trackEvent("product_viewed", {})
```

### Purchase revenue

An order fires an Optimizely purchase event with revenue in cents, value, and additional event tags.

Event

```
{
  "name": "order complete",
  "data": {
    "revenue_cents": 55500,
    "total": 555,
    "currency": "EUR",
    "item_count": 3
  },
  "context": {
    "shopping": [
      "complete",
      0
    ]
  },
  "globals": {
    "pagegroup": "shop"
  },
  "custom": {
    "completely": "random"
  },
  "user": {
    "id": "us3r",
    "device": "c00k13",
    "session": "s3ss10n"
  },
  "nested": [
    {
      "entity": "product",
      "data": {
        "id": "ers",
        "name": "Everyday Ruck Snack",
        "color": "black",
        "size": "l",
        "price": 420
      },
      "context": {
        "shopping": [
          "complete",
          0
        ]
      },
      "nested": []
    },
    {
      "entity": "product",
      "data": {
        "id": "cc",
        "name": "Cool Cap",
        "size": "one size",
        "price": 42
      },
      "context": {
        "shopping": [
          "complete",
          0
        ]
      },
      "nested": []
    },
    {
      "entity": "gift",
      "data": {
        "name": "Surprise"
      },
      "context": {
        "shopping": [
          "complete",
          0
        ]
      },
      "nested": []
    }
  ],
  "consent": {
    "functional": true
  },
  "id": "dbab8da5e9314af6",
  "trigger": "load",
  "entity": "order",
  "action": "complete",
  "timestamp": 1700000102,
  "timing": 3.14,
  "source": {
    "count": 1,
    "trace": "0a1b2c3d4e5f60718293a4b5c6d7e8f9",
    "type": "collector",
    "schema": "4"
  }
}
```

Mapping

```
{
  "name": "purchase",
  "settings": {
    "revenue": "data.revenue_cents",
    "value": "data.total",
    "eventTags": {
      "map": {
        "currency": "data.currency",
        "item_count": "data.item_count"
      }
    }
  }
}
```

Out

```
optimizely.trackEvent("purchase", {
  "revenue": 55500,
  "value": 555,
  "currency": "EUR",
  "item_count": 3
})
```

### Signup with attributes

A user signup sets per-event Optimizely attributes via setAttribute before firing the trackEvent.

Event

```
{
  "name": "user signup",
  "data": {
    "method": "google",
    "source": "referral"
  },
  "context": {
    "dev": [
      "test",
      1
    ]
  },
  "globals": {
    "lang": "elb"
  },
  "custom": {
    "completely": "random"
  },
  "user": {
    "id": "us3r",
    "device": "c00k13",
    "session": "s3ss10n"
  },
  "nested": [
    {
      "entity": "child",
      "data": {
        "is": "subordinated"
      }
    }
  ],
  "consent": {
    "functional": true
  },
  "id": "b1a581823f53e84c",
  "trigger": "test",
  "entity": "user",
  "action": "signup",
  "timestamp": 1700000103,
  "timing": 3.14,
  "source": {
    "count": 1,
    "trace": "0a1b2c3d4e5f60718293a4b5c6d7e8f9",
    "type": "collector",
    "schema": "4"
  }
}
```

Mapping

```
{
  "name": "signup",
  "settings": {
    "attributes": {
      "map": {
        "signup_method": "data.method",
        "referral_source": "data.source"
      }
    }
  }
}
```

Out

```
optimizely.setAttribute("signup_method", "google");

optimizely.setAttribute("referral_source", "referral");

optimizely.trackEvent("signup", {})
```

## Revenue[​](#revenue "Direct link to Revenue")

Optimizely expects revenue as an **integer in cents** (e.g. `7281` = `$72.81`). The destination passes the resolved value through without conversion. The caller must provide cents.

## Consent[​](#consent "Direct link to Consent")

Two layers protect event delivery:

1. **`config.consent`**: walkerOS gates delivery. Events are queued until required consent keys resolve to `true`.
2. **`on('consent')`**: the destination closes the Optimizely client (flushing queued events and stopping datafile polling) when any required key flips to `false`. On re-grant, the next push re-initializes the client.

```
destinations: {
  optimizely: {
    code: destinationOptimizely,
    config: {
      consent: { analytics: true },
      settings: {
        sdkKey: 'YOUR_SDK_KEY',
        userId: 'user.id',
      },
    },
  },
}
```

## Feature flags / decide()[​](#feature-flags--decide "Direct link to Feature flags / decide()")

This destination intentionally does **not** expose `decide()`. Experiment decisions belong in application code where UI branching happens. This package covers the outbound conversion-tracking use case.
