Connect your domain - Jam Documenation

Connecting Your Domain

Connecting your domain ties your website or web app to Jam so Recording Links capture console logs, network requests, and user interactions alongside the screen recording. Without a connected domain, screen recordings still work, but developer logs aren’t included. A connected domain lets Jam:

You need write access to your site to complete the steps below.

Every snippet on this page has a runnable example in the recording-links-demos repo, including HTML, Next.js, Angular, and Google Tag Manager.

Setup

  1. Install the Code Snippets
    Open Settings → Jam SDK and pick your framework. The snippet there has your Team ID filled in, and the picker keeps your selection in the address bar (for example, ?framework=angular), so you can share a link that opens on the right snippet.

Next to each snippet, click Copy agent prompt to get an install instruction with your Team ID and snippet filled in. Paste it into an AI coding agent like Claude Code or Cursor, and the agent installs the scripts for you.

Jam’s Recorder and Capture scripts must be served from the same origin as your site so recordings and logs are correctly associated. Find your Team ID in Settings → Jam SDK, then install the snippet for your framework on all pages, or at minimum on the URL that hosts your recording route.

Paste this into the <head> of every page.

   <meta name="jam:team" content="your-team-id" />
   <script type="module" src="https://js.jam.dev/recorder.js"></script>
   <script type="module" src="https://js.jam.dev/capture.js"></script>

Use next/script with strategy="beforeInteractive". Place the snippet in the root layout, not a nested route layout, since beforeInteractive is only honored from the root.

   import Script from "next/script";

export default function RootLayout({ children }: { children: React.ReactNode }) {
     return (
       <html lang="en">
         <head>
           <meta name="jam:team" content="your-team-id" />
         </head>
         <body>
           <Script
             src="https://js.jam.dev/recorder.js"
             type="module"
             strategy="beforeInteractive"
           />
           <Script
             src="https://js.jam.dev/capture.js"
             type="module"
             strategy="beforeInteractive"
           />
           {children}
         </body>
       </html>
     );
   }
   import { Html, Head, Main, NextScript } from "next/document";
   import Script from "next/script";

export default function Document() {
     return (
       <Html lang="en">
         <Head>
           <meta name="jam:team" content="your-team-id" />
         </Head>
         <body>
           <Script
             src="https://js.jam.dev/recorder.js"
             type="module"
             strategy="beforeInteractive"
           />
           <Script
             src="https://js.jam.dev/capture.js"
             type="module"
             strategy="beforeInteractive"
           />
           <Main />
           <NextScript />
         </body>
       </Html>
     );
   }

Install the package, then initialize it once from your root component. Wrap the call in ngZone.runOutsideAngular so the SDK’s listeners don’t trigger change detection.

   npm install @jam.dev/recording-links
import { Component, OnInit, NgZone } from '@angular/core';
import * as jam from '@jam.dev/recording-links/sdk';

@Component({ selector: 'app-root', template: '<router-outlet></router-outlet>' })
export class AppComponent implements OnInit {
  constructor(private ngZone: NgZone) {}
  ngOnInit() {
    this.ngZone.runOutsideAngular(() => {
      jam.initialize({ teamId: 'your-team-id' });
    });
  }
}

With the SDK, the recorder loads lazily. The recorder and capture scripts download only when someone opens a page through a Recording Link, so window.jam won’t exist on a normal page view.

Create a Custom HTML tag that fires on All Pages, and paste this in. It loads the same Recorder and Capture scripts as the other methods, with a guard so it runs once per page.

   <meta name="jam:team" content="your-team-id">
   <script>
   (function () {
     if (window.jam) return;
     var sources = [
       "https://js.jam.dev/recorder.js",
       "https://js.jam.dev/capture.js"
     ];
     for (var i = 0; i < sources.length; i++) {
       var script = document.createElement("script");
       script.type = "module";
       script.src = sources[i];
       document.head.appendChild(script);
     }
   })();
   </script>

GTM compiles Custom HTML tags as ES5, so it rejects async/await and dynamic import() with errors like “async function requires ECMASCRIPT_2017.” This snippet stays ES5 and injects the scripts as DOM elements, which avoids those errors.

What Each Script Does:

To serve one page to more than one workspace, add a jam:team meta tag per workspace.

Wait for both scripts to load successfully on your target URL before verifying your domain. Check that your Content Security Policy isn’t blocking them.

Performance Note: Jam caches assets aggressively to reduce load. For the plain HTML snippet, place the <script> tags as early as possible in <head>. Loading them with async, defer, or lazy import() can skip early logs and requests. The Next.js beforeInteractive strategy and the SDK handle this for you.

  1. Update Your Content Security Policy (if applicable)

If your site doesn’t define any Content Security Policy directives, skip this step. If your site sets a CSP with frame-src or script-src, add *.jam.dev to both. Otherwise, the Jam scripts are blocked.

   <meta
     http-equiv="Content-Security-Policy"
     content="frame-src 'self' *.jam.dev; script-src 'self' *.jam.dev;"
   />
  1. Verify Your Domain

After installing the scripts, verify your domain so Jam confirms they load and run correctly.

  1. Go to Settings → Jam SDK.
    1. Under Verify domain, paste the URL where the scripts are installed (for example, example.com or example.com/recorder).
    2. Click Verify.

Jam opens your URL and checks that:

On success, Jam confirms with a Domain successfully verified toast, the domain appears under Connect Domain marked Installed, and Recording Links from that domain capture console logs and network requests.

If your app redirects users from the recording URL (for example, sending unauthenticated users to a login page) keep all jam- query parameters through the redirect. The most important is jam-recording=.... Open your recording URL in an incognito window before verifying to check for unexpected redirects or parameter stripping.

Check Your Connection Status

Jam shows your connection status in two places, so you can tell at a glance whether a recording will capture logs:

Connect More Than One Domain

Once your first domain is verified, open Settings → Jam SDK and click Add another domain to connect the next site to the same workspace. This opens the same install and verify steps. Each connected domain appears in the list marked Installed, and shows up in the domain picker when you create a Recording Link.

Domain and Subdomain Behavior

In most cases, a recorder installed on the root domain (example.com) can capture events from subdomains (sub.example.com), and vice versa. Safari Limitation: In Safari, logs are only captured when the recorder and capture scripts run on the exact same subdomain. If Safari support is important for your team, install the recorder on the same subdomain where your users are active.

Current Limitations

Limitation Details
Browser support Fully supported in Chrome (including Incognito) and Firefox (including Private Windows). Supported in most Safari windows. Not supported in Safari Private Windows.
Iframes If the Capture script is installed inside an iframe, top-level page logs are not captured.
Script loading Scripts loaded with async, defer, or lazy import() may miss early console logs and network requests.
Verification required Installing scripts alone is not enough. You must verify your domain in Settings → Jam SDK.

FAQ

Can I put the Recorder and Capture scripts on different pages?
Yes. The <meta name="jam:team" /> tag must be present on any page where recorder.js is installed. It’s optional on pages that only include capture.js. Logs are only captured from pages where the Capture script is running.

Can I programmatically create Recording Links?
Not yet. Jam plans to expose an API for creating Recording Links programmatically (for example, from Slack, Zendesk, or directly within your app).

Can I customize the recorder UI?
Not currently. Contact Jam if you have specific customization requirements.

Can I mix Jam recordings with my own recording infrastructure?
No. Jam’s Recorder and Capture scripts must be used together. Due to browser storage and cross-origin restrictions, partial integrations or mixing with external recording systems are not supported.

If Verification Fails

When Jam can’t find the scripts on your URL, verification stops with Scripts not detected. Ensure both code snippets are installed here and try again. Common causes:

Fix the issue and retry verification.