Before you start
- Plan. Interleaving is in private beta for Enterprise customers. Ask your GrowthBook account team to enable it.
- SDKs. The JavaScript, React, and Node.js SDKs support interleaving from version 2.0.0. Other SDKs are not supported yet.
- Warehouses. The analysis unnests a JSON array in SQL. Redshift and Vertica are not supported yet.
- Rankers. Your ranking code must return a ranked list for a given config object. The config is authored in GrowthBook and handed to your code unchanged.
Step 1: Call interleave() in your code
Register the plugin on your GrowthBook instance and replace the call that fetches your ranked list with interleave().
interleave() evaluates targeting for the user. If they are in the experiment it calls getList() with each ranker’s config, drafts the two lists into one, and fires the exposure. Otherwise it serves the first ranker’s list. It returns:
Every option, return field, and fallback path is documented in the API reference at the bottom of this page.
Rules for rankingId and result
- One
rankingIdper query. A new search or page load is a new id. A filter change is a new query. Pagination continues the same draft: fetch the full lists once and page throughresult. - A user-selected sort is not a ranking. Pass
enabled: false. - Never re-sort or re-filter
result. It breaks the recorded positions and which items count as competitive. Apply diversity caps, pinned items, and filters inside each ranker’s list, before the merge.
Node.js and React
With the multi-userGrowthBookClient, register the plugin on the client and call interleave() with the user-scoped instance from createScopedInstance(). In React, register the plugin on the GrowthBook instance you pass to GrowthBookProvider and call interleave() with the instance from useGrowthBook().
Step 2: Track exposures
The plugin’sonExposure callback fires once per interleaved impression. Send it to your warehouse the same way you send “Experiment Viewed” events, keeping items as a JSON array in one column.
InterleaveExposure and InterleavedItem types in the API reference describe each field.
Step 3: Track engagement
Every engagement event you want to measure and attribute to a ranker, such as a click, add-to-cart, or order, must carry two extra properties:item_id(required): the same idgetItemId()returns.ranking_id(required for paired analysis): the impression the item was engaged with from. SpreadingtrackingPropsadds it, along withexperiment_id.
ranking_id is credited to the exact list that showed the item. Preference analysis works from item_id alone, which fits conversions logged by a system that never sees the list, such as an order recorded days later. See InterleaveTrackingProps in the API reference for the exact keys.
Step 4: Set up the Data Source
Add an Interleaving Exposure Query
An interleaving experiment reads exposures through an Interleaving Exposure Query, not an Experiment Assignment Query, because the shape is different: one row per impression with the item detail in a JSON array. Add one from your Data Source’s settings page under Interleaving Exposure Queries.
Each query declares one identifier type. Click Test query to check that the required columns come back. One query can serve every experiment on the Data Source.
Add item_id and ranking_id to your Fact Tables
Interleaving analyzes mean and proportion Fact Metrics. The Fact Table behind each metric must expose the engagement properties from Step 3 as columns with these exact names:
Add them to the Fact Table’s SQL:
ranking_id is missing or marked deleted, refresh the columns. GrowthBook validates the columns when you save the experiment and again on every results update, and names the missing column in the error.
Two things to know about ranking_id:
- Null is fine for preference analysis. Events logged by a system that never sees the list, such as orders, can leave
ranking_idnull. Preference analysis ignores the column. Paired analysis skips those rows, so do not add paired analysis to such a metric. - It must match exactly. The analysis joins on string equality with the exposure’s
ranking_id. Keep the id as the SDK emitted it: no prefix, no case change, no truncation.
Step 5: Create the experiment in GrowthBook
Go to Experiments → Interleaving and click Add Interleaving Experiment.
A ranker config is any JSON object your code understands. For the example above:
Via the REST API
Everything above is available through the REST API. A minimal create request:Step 6: Start it and check the data
An interleaving experiment is a draft until you start it. Starting adds it to the SDK payload for the enabled environments, and only exposures between start and stop are analyzed. Stopping or archiving removes it from SDK payloads immediately; results stay available. Shortly after starting, click Update on the Results tab. If no results appear, check that:- Exposure rows exist with the experiment’s tracking key as
experiment_id. - The SDK connection serves the environment you enabled, and the SDK version supports interleaving.
- Engagement events carry
item_id, andranking_idfor metrics with paired analysis. - Engagement timestamps are at or after the exposure’s
timestamp. If exposures are batched and land late, use a column that records when the list was shown rather than when the event was received.
API reference
The key functions and interfaces the SDK exports for interleaving, from@growthbook/growthbook/plugins. The type exports are shown as declarations, in the style of a .d.ts file.

