> ## 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.

# Install Subtext in a Next.js App Router Application

> Add the Subtext capture snippet to your Next.js App Router project by inserting it into app/layout.tsx using the Script component.

The fastest way to add Subtext to a Next.js App Router project is to drop the capture snippet into your root layout file. Because `app/layout.tsx` wraps every route in your application, the snippet loads once and records sessions across your entire site. The `<Script>` component from `next/script` handles deferred loading cleanly, keeping it out of the critical render path.

<Note>
  You can also run `npx @subtextdev/subtext-wizard` in your project root to have Subtext detect your framework and insert the snippet automatically. Follow this guide if you prefer to wire things up by hand.
</Note>

<Steps>
  <Step title="Find your Org ID">
    Log in to Subtext and open **Settings**. Your Org ID is listed in the **Capture** section. Copy it — you will paste it in place of `YOUR_ORG_ID` in the snippet below.
  </Step>

  <Step title="Open your root layout">
    Open `app/layout.tsx` (or `app/layout.jsx`) in your editor. This file exports the `RootLayout` component that wraps every page in your application.
  </Step>

  <Step title="Import the Script component">
    Add the following import at the top of `app/layout.tsx`, alongside your existing imports:

    ```tsx theme={null}
    import Script from 'next/script';
    ```
  </Step>

  <Step title="Add the capture snippet">
    Place a `<Script>` element with `strategy="afterInteractive"` inside your `<body>` tag, before any other children. Replace `YOUR_ORG_ID` with the Org ID you copied from Subtext settings.

    ```tsx app/layout.tsx theme={null}
    import Script from 'next/script';

    export default function RootLayout({
      children,
    }: {
      children: React.ReactNode;
    }) {
      return (
        <html lang="en">
          <body>
            <Script id="subtext-capture" strategy="afterInteractive">
              {`
                window['_fs_host'] = 'fullstory.com';
                window['_fs_script'] = 'edge.fullstory.com/s/fs.js';
                window['_fs_org'] = 'YOUR_ORG_ID';
                window['_fs_namespace'] = 'FS';
                !function(m,n,e,t,l,o,g,y){var s,f,a=function(h){return!(h in m)||(m.console&&m.console.log&&m.console.log('FullStory namespace conflict. More info: https://www.fullstory.com/developer/ns.html'),!1)};if(a(l)&&a(n)){m[l]={q:[]};var d=function(){return Array.prototype.slice.call(arguments,0)};m[l].identify=function(){m[l].q.push(["identify"].concat(d.apply(null,arguments)))};m[l].setUserVars=function(){m[l].q.push(["setUserVars"].concat(d.apply(null,arguments)))};m[l].event=function(){m[l].q.push(["event"].concat(d.apply(null,arguments)))};m[l].anonymize=function(){m[l].q.push(["anonymize"].concat(d.apply(null,arguments)))};m[l].shutdown=function(){m[l].q.push(["shutdown"].concat(d.apply(null,arguments)))};m[l].restart=function(){m[l].q.push(["restart"].concat(d.apply(null,arguments)))};m[l].log=function(a,b){m[l].q.push(["log",a,b])};m[l].consent=function(){m[l].q.push(["consent"].concat(d.apply(null,arguments)))};m[l].identifyAccount=function(){m[l].q.push(["identifyAccount"].concat(d.apply(null,arguments)))};m[l].clearUserCookie=function(){m[l].q.push(["clearUserCookie"].concat(d.apply(null,arguments)))};m[l].setVars=function(){m[l].q.push(["setVars"].concat(d.apply(null,arguments)))};m[l]._w={};y="XMLHttpRequest";m[l]._w[y]=m[y];y="fetch";m[l]._w[y]=m[y];if(m[y])m[l]._w[y]=m[y];m[l]._v="1.3.0";g=n.createElement(e);g.async=1;g.crossOrigin="anonymous";g.src='https://'+m[_fs_script];y=n.getElementsByTagName(e)[0];y.parentNode.insertBefore(g,y)}}(window,document,"script","_fs_config",n,o,g,y);
              `}
            </Script>
            {children}
          </body>
        </html>
      );
    }
    ```

    <Note>
      The `id` prop on `<Script>` is required by Next.js for any inline script. You can use any unique string — `"subtext-capture"` is a good default.
    </Note>
  </Step>

  <Step title="Deploy and verify">
    Deploy your application (or run `next dev` locally), then open it in a browser. Navigate to **Subtext → Sessions** and confirm that a new session appears within a minute or two.

    <Tip>
      Sessions typically appear within 30–60 seconds of page load. If nothing shows up after a few minutes, double-check that `YOUR_ORG_ID` was replaced with your actual Org ID and that the layout file is being served for the route you visited.
    </Tip>
  </Step>
</Steps>

<Note>
  The snippet records full production sessions and masks all form inputs by default. Your agent can flag additional PII and propose masking rules for your review from within Subtext.
</Note>
