> ## Documentation Index
> Fetch the complete documentation index at: https://subtext.fullstory.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Pendo and Subtext: From a Signal to the Session

> Attach the Subtext session URL to Pendo, then jump from any Pendo signal — a dismissed guide, an NPS detractor, a path drop-off — straight into the visitor's real session.

Pendo tells you *that* adoption moved: a guide was dismissed, a poll scored low, a path lost visitors. As product analytics with in-app guides, it can't show you what one specific visitor saw when they bailed. Subtext can. Attach the Subtext session URL to your Pendo visitor metadata and every Pendo signal becomes a jumping-off point — your agent reads the `subtext_url`, opens that visitor's real session, and walks the decisive moments with screenshots, the component tree, network, and console. Pendo detects; Subtext diagnoses.

<Note>
  This guide assumes the [Subtext capture snippet](/docs/install/overview) is installed and capturing sessions, and the Pendo agent snippet is installed on the page. No field setup is required — a value sent client-side via the snippet lands as agent metadata, which Pendo creates automatically the first time it receives it. Optionally give `subtext_url` a friendly display name under Pendo → Settings → Metadata.
</Note>

## Attach the session URL

Store the current Subtext session URL on the Pendo visitor so it travels with the visitor into every segment and report. It lands on the visitor's agent metadata, and the field needs no declaring first: Pendo creates the agent metadata the first time the snippet sends it.

Attach the URL with `pendo.updateOptions` once the visitor is known. In React, put it in the same `useEffect` as `FS('setIdentity')`. If the visitor is already known at boot, you can set it in the initial `pendo.initialize` call instead.

<CodeGroup>
  ```js pendo.updateOptions theme={null}
  const subtextUrl = FS('getSession', { format: 'url.now' })
  if (subtextUrl) {
    pendo.updateOptions({ visitor: { subtext_url: subtextUrl } })
  }
  ```

  ```tsx React theme={null}
  useEffect(() => {
    if (!user) return
    FS('setIdentity', { uid: user.id, properties: { email: user.email } })
    const subtextUrl = FS('getSession', { format: 'url.now' })
    if (subtextUrl) {
      pendo.updateOptions({ visitor: { id: user.id, subtext_url: subtextUrl } })
    }
  }, [user])
  ```

  ```js pendo.initialize theme={null}
  pendo.initialize({ visitor: { id: user.id, subtext_url: subtextUrl } })
  ```
</CodeGroup>

<Warning>
  Don't read `FS('getSession')` at module top level — it returns `null` until the session has started. The session URL also changes on a new session and when `FS('setIdentity')` is called with a different `uid`, so re-call `pendo.updateOptions` whenever you re-identify the visitor; the metadata is frozen until the next update. And don't call `pendo.initialize` twice — use `pendo.updateOptions` after the first initialize.
</Warning>

## From signal to session

However you first hear about a problem in Pendo — a low NPS score, a dismissed guide, a path that loses visitors — the path is the same: get to the `subtext_url`, then hand it to your agent for a Detect-vs-Diagnose read. Pendo flagged the drop or the low score; the session shows whether the guide rendered over the right element, whether the step was confusing, or whether something was simply broken.

<AccordionGroup>
  <Accordion title="An NPS or poll detractor notification">
    Pendo notifies you of a detractor: NPS 2 with a comment like *"the new dashboard is confusing."*

    Open the responding visitor: **Visitors** → visitor details → **Metadata** → copy `subtext_url`. Then hand it to your agent:

    ```text theme={null}
    A Pendo NPS detractor scored us 2 and said "the new dashboard is confusing." Here's their session:
    <PASTE subtext_url>

    Open it around their dashboard usage. What were they trying to do, where did they hesitate or
    get stuck, and is the confusion a real UX problem or a one-off? Ground their feedback in what
    actually happened on screen and point me to the moments.
    ```
  </Accordion>

  <Accordion title="A guide with low completion or high dismissal">
    Your Pendo guide engagement report shows an onboarding guide being dismissed far more than completed.

    Build a segment of visitors who dismissed the guide, open their visitor records, and copy `subtext_url` from each. Grab a few, then hand them to your agent:

    ```text theme={null}
    This Pendo onboarding guide is getting dismissed way more than completed. Here are sessions from
    visitors who dismissed it:
    <PASTE 3-4 subtext_urls>

    Review them. When the guide appeared, did it render correctly over the right element, or was it
    mis-positioned / covering something / firing at a bad moment? Tell me why people are dismissing
    it — bad timing, bad targeting, or bad copy — with evidence per session.
    ```
  </Accordion>

  <Accordion title="A path or funnel drop-off in the product review">
    A Pendo Paths or Funnels report shows visitors dropping at a specific step of a key workflow.

    Segment the dropped visitors and copy `subtext_url` from each visitor's metadata:

    ```text theme={null}
    Our Pendo funnel shows visitors dropping at the <step name> step. Here are sessions from visitors
    who dropped there:
    <PASTE subtext_urls>

    Walk each one to that step and tell me what stops them. Is it broken, slow, confusing, or are they
    just done? Find the common reason and show me the exact moment they give up.
    ```
  </Accordion>
</AccordionGroup>

<Tip>
  For a dismissed guide or a shared drop-off, ask your agent to roll the findings into one proof document (`doc-create`) — a screenshot of the guide as each dismisser actually saw it, plus a single shared link. Paste that back into the Pendo guide or report notes so the engagement number carries its cause.
</Tip>

## For agents

An autonomous agent can run the whole loop against Pendo directly: discover the friction, extract the `subtext_url`, and hand each session to the Subtext MCP. Pendo ships an official MCP server — remotely hosted, OAuth-authenticated, and it respects your existing Pendo permissions ([pendo.io/product/mcp](https://pendo.io/product/mcp/)). Use the MCP to confirm the metadata field and aggregate for hotspots; for deterministic single-visitor `subtext_url` reads, Pendo's REST API is exact.

<Steps>
  <Step title="Discover who is affected">
    Aggregate paths, funnels, guide engagement, or NPS and poll responses to find drop-offs and dismissals. Over the MCP, use the query tools (`activityQuery`, with an App ID from `list_all_applications`, plus `searchEntities` to find pages and features, `guideMetrics` for guide engagement, and `npsScore` for NPS). Over REST, POST the Aggregation API with a pipeline `source` — `pollsSeen` / `pollEvents` for NPS and polls, guide-engagement or path/funnel aggregations for dismissals and drop-offs, and visitor / feature / page activity for low-adoption hotspots.

    ```
    POST https://app.pendo.io/api/v1/aggregation
    # header: x-pendo-integration-key: <integration_key>
    # body: a pipeline with a `source`
    ```
  </Step>

  <Step title="Extract the session URL">
    Read `subtext_url` off the visitor's metadata. Confirm the field first with the MCP's `visitorMetadataSchema`, then read it deterministically per visitor over REST:

    ```
    GET https://app.pendo.io/api/v1/visitor/{visitor_id}
    # header: x-pendo-integration-key: <integration_key>
    # → response.metadata.agent.subtext_url
    ```

    `metadata` is grouped by origin (`agent`, `custom`, `salesforce`, ...): fields sent by the install snippet land under `metadata.agent`, while `custom` fields are added manually in Pendo or via the API — the snippet never writes them.
  </Step>

  <Step title="Hand off to Subtext">
    For each URL, call `review-open(session_url=<subtext_url>)` on the Subtext MCP → a Detect-vs-Diagnose summary: Pendo flagged the dismissal or the drop; the session shows whether the guide mis-positioned, mistimed, or covered the UI.
  </Step>
</Steps>

<Note>
  `subtext_url` only round-trips if it was written as visitor metadata at capture time (see [Attach the session URL](#attach-the-session-url)). Pendo's published tool list varies by source — the authoritative list is the Pendo help center, not third-party catalogs.
</Note>

## Related

* [Session Review overview](/docs/session-review/overview) — what your agent does once a session is open.
* [Install the capture snippet](/docs/install/overview) — required before any session URL exists to attach.
