# Install SourceLoop, script tag or npm SDK

The two ways to add SourceLoop (no-code script tag vs npm SDK), where each one goes, and how to verify it is working.

Source: https://sourceloop.ai/help/install-the-sourceloop-sdk/
Updated: 2026-06-29

---

There are two ways to add SourceLoop. They send data to the same place, so you can mix them.

| Method | Best for | Needs code? |
|---|---|---|
| **Script tag** | Marketing sites, no-code builders (WordPress, Webflow, Framer, Squarespace) | No, paste one snippet |
| **npm SDK** (`@sourceloop-analytics/sdk`) | Apps you build with code (React, Next.js, Vue, Node) | Yes, a few lines |

> **Use the same `websiteId` everywhere.** One SourceLoop website covers your marketing site *and* your app, including subdomains like `www.yoursite.com` and `app.yoursite.com`. Find your `websiteId` in the SourceLoop dashboard under **Settings, Tracking Code**.

## Option A, script tag (no code)

If your site is on a no-code platform (WordPress, Webflow, Framer, Squarespace) or you just want the fastest install, use the **script tag**: a single copy-paste snippet that auto-tracks pageviews, forms, and attribution with no code.

```html
<script>
  window.SourceLoopConfig = { websiteId: 'YOUR_WEBSITE_ID' };
</script>
<script async src="https://app.sourceloop.ai/tracking-v3.js"></script>
```

Full instructions (where to paste it per platform, options, and calling `window.sourceloop`) are in **[Install the tracking pixel »](/help/install-the-tracking-pixel/)**.

The rest of *this* guide covers the **npm SDK**, for apps you build with code. You can mix both: script on the marketing site, SDK in the app, just use the same `websiteId`.

## Option B, npm SDK (for coded apps)

One package gives you both a browser client and a server client.

```bash
npm install @sourceloop-analytics/sdk
```

- **Browser code:** `import { ... } from '@sourceloop-analytics/sdk'`
- **Server code:** `import { ... } from '@sourceloop-analytics/sdk/server'`

The server client requires **Node 18+** (it uses the built-in `fetch`).

### 1) Browser, initialize once

Call `init()` as early as possible, once per page load. In Next.js App Router, put it in a client component rendered from the root layout.

```tsx
// app/sourceloop-init.tsx
'use client';
import { useEffect } from 'react';
import { init } from '@sourceloop-analytics/sdk';

export function SourceLoopInit() {
  useEffect(() => {
    init({ websiteId: 'YOUR_WEBSITE_ID' });
  }, []);
  return null;
}
```

```tsx
// app/layout.tsx
import { SourceLoopInit } from './sourceloop-init';

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html>
      <body>
        <SourceLoopInit />
        {children}
      </body>
    </html>
  );
}
```

`init()` loads the same tracking script under the hood, so pageviews (including SPA navigations), forms, and attribution are captured automatically. You only write code for the things the script cannot see (signups, checkouts).

### 2) Browser, track and identify

```ts
import { identify, track, reset, checkoutMetadata } from '@sourceloop-analytics/sdk';

identify({ email: user.email });               // on login/signup (idempotent)
track('signup_completed', { plan: 'pro' });    // a conversion you want recorded
reset();                                        // on logout
const meta = checkoutMetadata();                // { sourceloop_anonymous_id } for client checkouts
```

### 3) Server, for OAuth signups and payments

The server client reads the visitor's id from the request cookie and binds it. This is the reliable way to attribute things that happen on your backend (Google/GitHub login, Stripe checkout). See [Track SaaS signups, trials, and subscriptions](/help/track-saas-signups-and-subscriptions/) for full examples.

```ts
import { Sourceloop, getAnonymousId, checkoutMetadata } from '@sourceloop-analytics/sdk/server';

const sl = new Sourceloop({ websiteId: 'YOUR_WEBSITE_ID' });

const anonymousId = getAnonymousId(req);  // reads the _sl_aid cookie off the request
await sl.identify({ anonymousId, email: user.email });
await sl.track({ anonymousId, email: user.email, eventName: 'signup_completed' });
```

### Your website id is not a secret

Paste your `websiteId` straight into the code, both in the browser and on the server. It is already visible in your site's tracking snippet, so there is nothing to hide and **no environment variable to set up**. (If you prefer env vars for managing multiple environments you still can, but it is optional.)

## Which install goes where

| Where | Install | What it captures |
|---|---|---|
| Marketing site (WordPress/Webflow/...) | Script tag | pageviews, forms, attribution |
| App frontend (React/Next/Vue) | `@sourceloop-analytics/sdk` (or script tag) | pageviews, `identify` on login, client checkout metadata |
| App backend (Node/Next API routes) | `@sourceloop-analytics/sdk/server` | OAuth signups, server-side checkout stitching, server conversions |

You do **not** need a separate SourceLoop account or website id per surface, one website id covers everything.

## Verify it is working

1. Open your site, then open the browser DevTools, **Application, Cookies**. You should see a `_sl_aid` cookie set on your root domain (e.g. `.yoursite.com`).
2. In DevTools, **Network**, filter by `sourceloop`. You should see requests firing on pageview.
3. In your SourceLoop dashboard, the visit should appear in real-time analytics within a few seconds.
4. If you wired `identify`/`track`, trigger them (log in / sign up) and confirm the lead/conversion shows in the dashboard.

### Troubleshooting

- **No `_sl_aid` cookie:** the snippet is not on the page, or `websiteId` is wrong. View source and confirm the snippet is present with the correct id.
- **Nothing in the dashboard:** check the `websiteId` matches your dashboard, and that you are not blocking the request with an ad blocker while testing.
- **`@sourceloop-analytics/sdk` import errors on the server:** make sure you are on Node 18+ and importing server helpers from `@sourceloop-analytics/sdk/server` (not the root).
- **`identify`/`track` "did nothing":** on the script-tag path, make sure `window.sourceloop` exists (the script loaded). With the SDK, make sure `init()` ran first.

## Frequently Asked Questions

### Do I need a separate SourceLoop account or website id per surface?

No. One website id covers your marketing site and your app, including subdomains like www.yoursite.com and app.yoursite.com. Use the same websiteId in the script tag and in the SDK so the journey stays as one visitor. You find your websiteId in the dashboard under Settings, Tracking Code.

### Is my website id a secret?

No. Paste it straight into your code, in the browser and on the server. It is already visible in your site's tracking snippet, so there is nothing to hide and no environment variable to set up. If you prefer env vars to manage multiple environments you still can, but it is optional.

### Can I use the script tag and the npm SDK together?

Yes. They send data to the same place, so a common setup is the script tag on your marketing site and the SDK in your app. Just use the same websiteId everywhere.

### What Node version does the server client need?

Node 18 or newer. The server client uses the built-in fetch, which is available from Node 18. Import server helpers from "@sourceloop-analytics/sdk/server", not the package root.
