Skip to content New SourceLoop MCP: chat with your attribution data in Claude, ChatGPT & Cursor
SourceLoop
Tracking pixel

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.

On this page
  1. Option A, script tag (no code)
  2. Option B, npm SDK (for coded apps)
  3. 1) Browser, initialize once
  4. 2) Browser, track and identify
  5. 3) Server, for OAuth signups and payments
  6. Your website id is not a secret
  7. Which install goes where
  8. Verify it is working
  9. Troubleshooting

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

MethodBest forNeeds code?
Script tagMarketing 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.

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

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.

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.

// 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;
}
// 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

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 for full examples.

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

WhereInstallWhat it captures
Marketing site (WordPress/Webflow/…)Script tagpageviews, 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/serverOAuth 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

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

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

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

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

Track every conversion to its true source

Capture and send full attribution data from every signup, lead, booking, and sale to your CRM and ad platforms, so you know exactly what's driving revenue.

Without SourceLoop

Untagged

Kayden Floyd

kayden@abc.com

  • SourceUnknown
  • MediumUnknown
  • CampaignUnknown
  • Landing pageUnknown
Journey
No touchpoints captured

With SourceLoop

Auto-tagged

Kayden Floyd

kayden@abc.com · Acme Co.

  • Channel Paid Social
  • CampaignFree_demo
  • Landing page/pricing
Journey
Synced to HubSpot Google Ads Meta