Skip to main content
Statsig tells you that a variant moved a metric: a scorecard turned red, a guardrail tripped, a conversion dropped in the treatment. It can’t tell you why one exposed person got stuck. Subtext can. Attach the Subtext session URL to your Statsig user object and every Statsig signal becomes a jumping-off point — your agent reads the subtext_url, opens that person’s real session, and walks the decisive moments with screenshots, the component tree, network, and console. Statsig detects; Subtext diagnoses.
This guide assumes the Subtext capture snippet is installed and capturing sessions, and the Statsig JS client (@statsig/js-client) is initialized.

Attach the session URL

Store the current Subtext session URL on your Statsig user object so it travels with the signal. There are two places to attach it, depending on how precise the link needs to be.

On the user object

Attach the URL to the Statsig user’s custom field via updateUserAsync. Custom fields ride along on every subsequent exposure and logEvent call, so they show up in the logs that back your experiments. Call it wherever your app already identifies the user — on auth resolution, not at module top level.

On a specific event

When the exact moment matters, pass the URL directly on a single logEvent call. url.now carries a timestamp, so the link opens the replay at that instant — ideal for high-signal events like errors and conversion failures.
Don’t read FS('getSession') at module top level — it returns null until the session has started, and don’t call updateUserAsync before client.initializeAsync has resolved. When spreading into updateUserAsync, keep the rest of the user object (and existing custom) so you don’t wipe targeting attributes. The session URL changes on a new session and when FS('setIdentity') is called with a different uid, so re-call updateUserAsync whenever you re-identify — the custom field is frozen at set-time. In event metadata, don’t use dotted keys (subtext.url): Statsig parses . as a nested path and can null the value. Store subtext_url.

From signal to session

However you first hear about a problem in Statsig, the path is the same: get to the subtext_url, then hand it to your agent for a Detect-vs-Diagnose read. The scorecard says the variant regressed; the session shows whether the new feature rendered correctly, errored, or simply confused people.
Statsig posts to Slack: “⚠️ Guardrail checkout_error_rate triggered on experiment new-cart-v2, treatment group.”Open the experiment and drill into the affected treatment users via Pulse / the Users tab. Inspect a recent exposure for one of them and copy subtext_url from the custom fields. Grab a few, then hand them to your agent:
In the weekly experiment review, a variant’s scorecard is red on a key metric and someone asks “but why?”In the Statsig Console, open the Users tab, enter a userID from the regressed cohort, and read custom.subtext_url off the most recent exposure.
You spot one user in the Events Explorer who got the treatment and had a clearly bad outcome.Open that log line and copy subtext_url from the user custom fields or the event metadata.
For a regression spanning several exposed users, ask your agent to assemble one proof document (doc-create) with a screenshot per exposure and a single shared link — then paste that back into the experiment’s notes or the readout deck so the scorecard number carries its explanation.

For agents

An autonomous agent can run the whole loop against Statsig: discover the regressed variant, extract the subtext_url, and hand each session to the Subtext MCP. Statsig ships an official MCP server at https://api.statsig.com/v1/mcp (remote, HTTP), authenticated with a statsig-api-key header (a Console API key — read keys get read tools) or OAuth. Its tools front the Console API (experiments, gates, dynamic configs, layers, metrics, segments, autotunes), for example Get_List_of_Experiments and Get_Experiment_Details_by_ID. Docs: docs.statsig.com/integrations/mcp.
For this workflow the MCP is discovery-only: no MCP tool returns exposure records or the user custom fields where subtext_url is stored, and no documented Console-API endpoint returns a single exposure record by ID with its custom field — that value lives in the warehouse, not the Console API. Extraction is warehouse- or webhook-based (see step 2); the warehouse route requires Statsig’s Enterprise tier — non-Enterprise projects must use the Event Webhook.
1

Discover the regressed variant

Use the MCP tools (Get_List_of_Experiments, Get_Experiment_Details_by_ID) or the Console API directly — base https://statsigapi.net/console/v1, header STATSIG-API-KEY, version 20240601:
Near-real-time affected-user and event signals come from the Event Webhook, which forwards exposure, gate, and experiment events to your endpoint.
2

Extract the session URL

Read subtext_url from the warehouse exposures table (best fit) — e.g. experimentation.statsig.exposures. This table only exists with warehouse access to exposures, which is Enterprise-tier on Statsig: Data Warehouse Exports are Enterprise-only, and Warehouse Native is likewise part of the Enterprise tier. On Developer or Pro plans, capture subtext_url via the Event Webhook instead. The user_dimensions column is JSON of the user’s attributes at first exposure:
Databricks
The JSON-extraction syntax varies by warehouse — e.g. JSON_VALUE(user_dimensions, '$.subtext_url') on BigQuery, PARSE_JSON(user_dimensions):subtext_url on Snowflake, JSON_EXTRACT_PATH_TEXT(user_dimensions, 'subtext_url') on Redshift.If you logged subtext_url on a custom event instead, it lands in that event’s metadata.
3

Hand off to Subtext

For each URL, call review-open(session_url=<subtext_url>) on the Subtext MCP. Event-level URLs are moment-precise, so the review opens exactly when the signal fired.
subtext_url only round-trips if it was emitted into the exposure stream (as a user attribute) or onto a custom event at instrumentation time (see Attach the session URL). Event-level links are moment-precise; user- and exposure-level links open at session start.