Exposures and Rewards
How Levered tracks variant impressions and success events through your data warehouse to train bandit models.
Levered learns from two types of events: exposures (when a user sees a variant) and rewards (when a user does something valuable). Both live in your data warehouse. Levered reads them, joins them together, and uses the result to train models.
Exposures
An exposure is recorded when a user is shown a variant. It captures what the user saw and who they are.
When you integrate the Levered SDK, you provide an onExposure callback. This fires every time a variant is served to a user. Your callback is responsible for logging the exposure to your warehouse (BigQuery or Snowflake).
A typical exposure record includes:
| Field | Description |
|---|---|
anonymous_id | A unique identifier for the user or session |
optimization_id | Which optimization this exposure belongs to |
variant | The specific combination of design feature levels that was served |
timestamp | When the exposure occurred |
| Context values | Any context feature values (country, device type, etc.) |
You own the schema. Levered just needs to know how to query it.
Rewards
A reward is the success event you are optimizing for. It represents the outcome you want to maximize.
Rewards can be:
- Boolean -- the user converted or did not. Examples: signed up, completed checkout, clicked a CTA.
- Numeric -- a continuous value. Examples: revenue amount, time on page, number of items purchased.
Reward events are logged to your warehouse through your existing analytics pipeline. Levered does not require a special SDK call for rewards -- it reads them from the SQL query you define as your metric.
A typical reward record includes:
| Field | Description |
|---|---|
anonymous_id | The same user identifier used in exposures |
value | The reward value (1/0 for boolean, or a numeric amount) |
timestamp | When the reward event occurred |
Attribution
A reward on its own does not mean anything until it is connected to an exposure. Levered needs to know: which variant was this user seeing when they converted?
Levered uses last-touch attribution with a configurable conversion window (default: 24 hours). Here is how it works:
- A reward event comes in for a user.
- Levered looks back at that user's exposures within the conversion window.
- The most recent exposure before the reward is credited.
- If no exposure exists within the window, the reward is not attributed.
This means if a user sees variant A at 10:00 AM and converts at 2:00 PM the same day, the conversion is attributed to variant A. If they convert 3 days later (outside the default 24-hour window), the reward is not attributed to any variant.
You can adjust the conversion window based on your product's typical conversion timeline. A checkout optimization might use a 1-hour window. A subscription decision might use a 7-day window.
Observations
Observations are the joined dataset of exposures and rewards. This is what the model actually trains on.
For each exposure, Levered determines whether a reward occurred within the conversion window. The result is a table where each row represents one exposure and its outcome:
| anonymous_id | variant | reward | context |
|---|---|---|---|
| user_abc | {"headline": "Start free", "cta": "Sign up"} | 1 | {"country": "US"} |
| user_def | {"headline": "Boost revenue", "cta": "Get started"} | 0 | {"country": "DE"} |
| user_ghi | {"headline": "Start free", "cta": "Get started"} | 1 | {"country": "US"} |
The model uses this table to learn which variants produce rewards (and for CMAB models, which variants work best for which contexts).
The data flow
Here is the end-to-end flow from user interaction to model training:
1. User visits your site
|
2. SDK requests a variant from Levered API
|
3. Levered returns the optimal variant
|
4. Your app renders the variant
|
5. onExposure callback fires -> you log to your warehouse
|
6. User converts (or doesn't)
|
7. Your analytics pipeline logs the reward to your warehouse
|
8. Levered queries your warehouse, joins exposures + rewards
|
9. Model trains on the joined observations
|
10. Next user gets a better variant selectionThe key insight: Levered reads from your warehouse. You own the data pipeline. Levered never stores your raw event data. It queries your warehouse using the metric SQL you define, builds observations, and trains models. Your data stays in your infrastructure.
Defining metrics
Metrics are the SQL queries that tell Levered how to find rewards in your warehouse. You write standard SQL that returns rows with at least an anonymous_id, a reward value, and a timestamp.
For example, a sign-up conversion metric might look like:
SELECT
anonymous_id,
1 AS value,
created_at AS timestamp
FROM your_schema.sign_ups
WHERE created_at >= CURRENT_DATE - INTERVAL '30 days'Include a time filter to avoid scanning your full history on every training run. Levered runs this query against your warehouse, joins the results with exposure data, and produces the observations table that feeds the model.