@nurdd/web-sdk

Framework-agnostic attribution & analytics SDK for the browser. Works with Vanilla JS, React, Next.js, Vue, Nuxt, Angular, Remix, and SvelteKit.
661
Install
npm install @nurdd/web-sdk
Latest Version:2.0.0
Vue:3
Last Updated:Oct 1, 2026
Links: npm
Maintainer: darshan-j

@nurdd/web-sdk

Framework-agnostic attribution & analytics SDK for the browser, powered by Nurdd. One package, one integration, every popular frontend — measure where your traffic, signups and revenue actually come from without building a data pipeline.

Framework Import path Helper
Vanilla JS <script> UMD or ESM Nurdd.initSdk({...})
React @nurdd/web-sdk/react <NurddProvider>, useNurdd()
Next.js (App Router) @nurdd/web-sdk/next <NurddProvider>, <NurddPageView />
Vue 3 @nurdd/web-sdk/vue NurddPlugin, useNurdd()
Nuxt 3 @nurdd/web-sdk/nuxt plugins/nurdd.client.ts
Angular @nurdd/web-sdk/angular provideNurdd(), NurddService
Remix / SvelteKit / Solid core import createSdk({...})

Table of contents

Features

  • Event tracking with offline buffering and automatic retries
  • Session tracking with automatic idle expiry
  • Conversion tracking (purchase, signup, custom goals)
  • Deep-link attribution, including deferred (post-install) flows
  • Campaign & UTM tracking with auto-strip after capture
  • Cross-platform identity mapping
  • Auto-tracking: SPA page views, outbound clicks, unload-time flush
  • SSR-safe: no window access during server rendering
  • Zero runtime dependencies

Everything shows up in your Nurdd dashboard, ready to slice by campaign, cohort and conversion.

Prerequisites

  • A Nurdd account.
  • A public SDK key and your API URL — see Getting your API key.
  • A modern browser build target (ES2019+). Framework adapters require the matching framework as a peer dependency (React ≥ 16.8, Vue ≥ 3, Angular ≥ 12).

Getting your API key

API keys are issued to you by a Brand from inside the Nurdd app — you cannot generate them yourself. To receive a key:

  1. The Brand logs in to the Nurdd app.
  2. They open Settings → SDK Setup.
  3. They enter your (the developer's) email address.
  4. Nurdd shares the API key with you.

Use the key you receive as your sdkKey. If you don't have one yet, ask your Brand contact to complete the SDK Setup step above.

Install

npm install @nurdd/web-sdk
# or
yarn add @nurdd/web-sdk
# or
pnpm add @nurdd/web-sdk

For frameworkless <script> use, load the prebuilt UMD bundle from the Nurdd CDN:

<script src="https://cdn.nurdd.club/web-sdk/nurdd-sdk.umd.js"></script>

Quick start

import { initSdk } from "@nurdd/web-sdk";

const sdk = initSdk({
  sdkKey: "sdk_pk_xxx", // the key your Brand shared with you
  baseUrl: "https://api.nurdd.com", // your Nurdd API URL
});

sdk.track("button_clicked", { button: "hero_cta" });
sdk.identify("user_42", { email: "user@example.com" });
sdk.conversion("purchase", { value: 49.99, currency: "USD" });

Page views, sessions and campaign attribution are tracked automatically from here — see the framework guides for the idiomatic setup in your stack.

Configuration

Option Default What it does
sdkKey (required) — Your public SDK key from the Nurdd dashboard
baseUrl (required) — Your Nurdd API URL (e.g. https://api.nurdd.com)
appVersion null Forwarded with every event for cohort analysis
debug false Verbose console output
flushIntervalMs 5000 Background queue flush cadence
maxBatchSize 50 Max events per batched request
sessionTimeoutMs 1800000 Idle-session expiry (30 min)
autotrack.pageViews true Wire history navigation to page_view
autotrack.outboundClicks false Track cross-origin anchor clicks
autotrack.flushOnUnload true Flush pending events on page hide
stripUtmFromUrl true Remove UTM params from the URL after first read

Framework guides

Vanilla JS / HTML

<!doctype html>
<html>
  <body>
    <script src="https://cdn.nurdd.club/web-sdk/nurdd-sdk.umd.js"></script>
    <script>
      const sdk = Nurdd.initSdk({
        sdkKey: "sdk_pk_xxx",
        baseUrl: "https://api.nurdd.com",
      });

      sdk.track("button_clicked", { button: "hero_cta" });
      sdk.identify("user_42", { email: "user@example.com" });
      sdk.conversion("purchase", { value: 49.99, currency: "USD" });

      sdk.onDeepLink((dl) => {
        if (dl.deep_link_path) location.href = dl.deep_link_path;
      });
    </script>
  </body>
</html>

ESM equivalent (with a bundler):

import { initSdk } from "@nurdd/web-sdk";
const sdk = initSdk({ sdkKey: "sdk_pk_xxx", baseUrl: "https://api.nurdd.com" });
sdk.track("page_loaded");

React

// app.tsx
import { NurddProvider } from "@nurdd/web-sdk/react";

export function App() {
  return (
    <NurddProvider
      config={{ sdkKey: "sdk_pk_xxx", baseUrl: "https://api.nurdd.com" }}
    >
      <Routes />
    </NurddProvider>
  );
}

// any component
import { useTrack, useIdentity, useDeepLink } from "@nurdd/web-sdk/react";

function CheckoutButton({ priceId }) {
  const track = useTrack();
  return (
    <button onClick={() => track("checkout_started", { priceId })}>Buy</button>
  );
}

function Boot() {
  const { identify } = useIdentity();
  useDeepLink((dl) => {
    if (dl.deep_link_path) navigate(dl.deep_link_path);
  });
  useEffect(() => {
    identify("user_42", { email: "user@example.com" });
  }, []);
  return null;
}

Next.js (App Router)

// app/providers.tsx — Client Component
"use client";
import { NurddProvider } from "@nurdd/web-sdk/next";
export default function Providers({ children }) {
  return (
    <NurddProvider
      config={{ sdkKey: "sdk_pk_xxx", baseUrl: "https://api.nurdd.com" }}
    >
      {children}
    </NurddProvider>
  );
}

// app/page-view.tsx
("use client");
import { usePathname, useSearchParams } from "next/navigation";
import { NurddPageView } from "@nurdd/web-sdk/next";
export default function PageView() {
  return (
    <NurddPageView pathname={usePathname()} searchParams={useSearchParams()} />
  );
}

// app/layout.tsx
import Providers from "./providers";
import PageView from "./page-view";
export default function RootLayout({ children }) {
  return (
    <html>
      <body>
        <Providers>
          <PageView />
          {children}
        </Providers>
      </body>
    </html>
  );
}

Vue 3

// main.ts
import { createApp } from "vue";
import { NurddPlugin } from "@nurdd/web-sdk/vue";
import App from "./App.vue";

createApp(App)
  .use(NurddPlugin, {
    sdkKey: "sdk_pk_xxx",
    baseUrl: "https://api.nurdd.com",
  })
  .mount("#app");
<!-- any component -->
<script setup>
import { useRoute } from "vue-router";
import { useNurdd, trackPageViews, useIdentity } from "@nurdd/web-sdk/vue";

const sdk = useNurdd();
trackPageViews(useRoute());
const { identify } = useIdentity();

function buy() {
  sdk.conversion("purchase", { value: 19.0, currency: "USD" });
}
</script>

Nuxt 3

// nuxt.config.ts
export default defineNuxtConfig({
  runtimeConfig: {
    public: {
      nurdd: { sdkKey: "sdk_pk_xxx", baseUrl: "https://api.nurdd.com" },
    },
  },
});
// plugins/nurdd.client.ts
export { default } from "@nurdd/web-sdk/nuxt";
<!-- any component -->
<script setup>
const { $nurdd } = useNuxtApp();
$nurdd.track("hero_viewed");
</script>

Angular (standalone)

// app.config.ts
import { ApplicationConfig } from "@angular/core";
import { provideNurdd } from "@nurdd/web-sdk/angular";

export const appConfig: ApplicationConfig = {
  providers: [
    provideNurdd({ sdkKey: "sdk_pk_xxx", baseUrl: "https://api.nurdd.com" }),
  ],
};
// any.component.ts
import { Component, inject } from "@angular/core";
import { NurddService } from "@nurdd/web-sdk/angular";

@Component({
  selector: "buy-btn",
  template: `<button (click)="buy()">Buy</button>`,
})
export class BuyButton {
  private nurdd = inject(NurddService);
  buy() {
    this.nurdd.conversion("purchase", { value: 9.99, currency: "USD" });
  }
}

Remix / SvelteKit / Solid

The core works anywhere — import createSdk and store the instance somewhere global (a Remix loader context, a Svelte store, a Solid signal, etc.). Every server-only render is a no-op.

import { createSdk } from "@nurdd/web-sdk";
export const nurdd = createSdk({
  sdkKey: "sdk_pk_xxx",
  baseUrl: "https://api.nurdd.com",
});
if (typeof window !== "undefined") nurdd.init();

Public API

sdk.init();                            // idempotent; safe to call anytime
sdk.track(eventName, properties?, options?);
sdk.page(name?, properties?);
sdk.identify(externalUserId, traits?);
sdk.reset();                           // clear the current user on logout
sdk.conversion(type, { value?, currency?, campaignId?, attribution? });
sdk.onDeepLink(listener);              // returns an unsubscribe fn
sdk.flush();                           // deliver pending events now
sdk.endSession();
sdk.destroy();
sdk.info();                            // diagnostics

Every method is safe to call before init() resolves — events are queued locally and shipped on the next flush.

React / Vue hooks

useNurdd(); // the SDK instance
useTrack(); // (event, properties?) => void
useIdentity(); // { identify(userId, traits?), reset() }
useDeepLink(cb); // run a callback when the user arrives from a campaign link

How it works

The SDK is offline-first and designed to never lose an event:

  • Events are persisted locally before the network call, so a tab crash or a dropped connection can't lose them — they retry automatically on reconnect.
  • On page hide, pending events are flushed reliably so last-mile events still ship.
  • Attribution captured from a landing URL (UTM/campaign) is remembered and stamped onto later conversions, so a signup or purchase still credits the original campaign even after the URL is cleaned up.

Best practices

  • Initialise once near the root of your app and reuse the single instance.
  • Call identify() on login/signup so anonymous activity is stitched to the known user, and reset() on logout.
  • Let attribution flow automatically — record a conversion() and the SDK credits the campaign the visitor arrived from, with no extra wiring.
  • Keep only your public key in the browser. The public key is safe to ship; never embed a server key in client code.
  • Add flushOnUnload-friendly events rather than blocking navigation to send data — the SDK already handles unload flushing.

Troubleshooting

Symptom Likely cause & fix
sdkKey is required / baseUrl is required Pass both sdkKey and baseUrl to initSdk/createSdk.
Nothing appears in the dashboard Enable debug: true and check the console; confirm the key and API URL.
CORS / origin errors in the browser Add your site's origin to the key's allow-list in the dashboard.
Conversions not attributed to a campaign Ensure the visitor arrived via a Nurdd campaign link before converting.
Duplicate page views in an SPA Use the framework's page-view helper instead of tracking manually.
Events delayed This is expected — events batch and flush every flushIntervalMs; call sdk.flush() to force delivery.

FAQ

Is the SDK safe to render on the server? Yes. It never touches window during SSR; browser-only work is deferred to the client.

Does it add runtime dependencies? No. The core has zero runtime dependencies. Framework adapters use the framework you already have as an optional peer dependency.

Can I run more than one instance? Yes. Use createSdk() for isolated instances (e.g. multi-tenant), or initSdk() for the common single-instance case.

Where do I get my key and API URL? Your key is issued to you by a Brand from the Nurdd app — see Getting your API key. You cannot generate one yourself.

Versioning

This package follows semantic versioning. The SDK talks to a versioned Nurdd API, so a new major version of the SDK can adopt a new API version while existing apps keep working unchanged. Pin a major version and upgrade deliberately.

Related Packages

@indiebob/tracker

Privacy-first analytics SDK for web applications. <5KB gzipped. No cookies.

1,131
@hellyeah/x-ray

Multi-platform analytics SDK for browser, React, Next.js, Remix, Vue, Svelte, Nu...

20,021
@outlit/browser

Browser tracking SDK for Outlit customer context with React and Vue bindings

73,549 6
@loomail/browser

Browser client for Loomail: identify people and track events from any web app, w...

410 0
@edgeone/framework-detect

A framework detection library for web projects

169,969

Version History

Version Released Vue License
2.0.0 >=3.0.0