Quickstart

~5 minSDK @adtivity/adtivity-sdkv1.0.3

Adtivity turns your product, payment and on-chain data into a signal you can read, share and act on. There are two ways in — pick the one that matches how you build.

Path 1 — available now

📦 NPM SDK

Drop @adtivity/adtivity-sdk into your web app. Auto-tracks page views, clicks, geolocation and identity with a single init().

Install the SDK →
Path 2 — MCP-native Beta

🤖 MCP Server

Point Claude, Cursor or any MCP-compatible agent at Adtivity. Query your metrics in plain English — no SDK, no SQL.

Connect MCP →
You can run both at the same timeThe SDK collects events from your product. The MCP server reads them back to your AI. Same workspace, same API key.

MCP Server Beta

adtivity-mcp is an AI-native setup assistant. Add it once to Claude Code or Cursor, tell your agent “Install Adtivity into this project”, and it detects your framework, installs the SDK, patches your entry file, and verifies the integration — no manual steps, no config wrestling.

Claude Code

Run once in your terminal. Claude Code picks it up on the next session.

Terminal
claude mcp add adtivity -- npx adtivity-mcp

To use it across all your projects, add it globally:

claude mcp add --scope user adtivity -- npx adtivity-mcp

Cursor / Claude Desktop / Windsurf

Add to ~/.cursor/mcp.json (or the project-level .cursor/mcp.json):

mcp.json
{
  "mcpServers": {
    "adtivity": {
      "command": "npx",
      "args": ["adtivity-mcp"]
    }
  }
}

Five tools, one prompt

When you say “Install Adtivity”, the agent runs these tools in order:

ToolWhat it does
adtivity_detect_frameworkReads package.json — identifies Next.js App/Pages Router, React, Vue, Express, or React Native and finds the right entry file.
adtivity_install_sdkRuns npm/yarn/pnpm/bun install @adtivity/adtivity-sdk using your detected package manager.
adtivity_write_init_codeCreates AdtivityProvider.tsx (Next.js App Router) or patches your entry file with init(), initPageTracking(), and initClickTracking().
adtivity_wrap_eventReturns a ready-to-paste trackEvent() snippet for any named action — signup, upgrade, checkout, and more.
adtivity_verify_integrationChecks SDK installed, init code present, and API key configured. Returns a pass / warn / fail checklist.

Quick test

Confirm the server starts before adding it to your AI client:

Terminal
npx adtivity-mcp

The process will hang — that means it's listening on stdio and is ready. Press Ctrl+C to exit.

Once connected to Claude Code or Cursor, open any project and try the prompt below. The demo shows you exactly what the agent will do:

Claude Code — adtivity MCP

Click “Run demo” to see what happens when you ask your AI to install Adtivity.

Prompts that work well

After setup, you can also use the MCP tools individually:

PromptWhat happens
“Install Adtivity into this project”Runs all five tools in sequence — detect, install, init, verify.
“Add Adtivity event tracking to my checkout button”Calls adtivity_wrap_event and pastes the snippet into your component.
“Is Adtivity set up correctly in this project?”Runs adtivity_verify_integration and reports the checklist.
“What framework is this project using?”Calls adtivity_detect_framework and summarises the result.
💡
The track names you choose become the vocabulary your AI usesNaming a button signup-cta-hero vs btn-1 changes whether your agent can answer “how is the hero CTA doing?”.

Installation

Install the Adtivity SDK from npm. The package name is @adtivity/adtivity-sdk — note the double adtivity.

npm
npm install @adtivity/adtivity-sdk

React Native — also install the async storage peer dependency:

npm install @react-native-async-storage/async-storage

The SDK ships as a single isomorphic package for both browser and React Native environments.

Authentication

The Adtivity SDK authenticates with a single API key. There's no separate sign-in step or token exchange — the key you pass to init() identifies your project for every event the SDK sends.

Find your key in Settings → API Keys in the Adtivity dashboard. Expose it to your client through a public env var, e.g. NEXT_PUBLIC_ADTIVITY_API_KEY.

The SDK key is public by designIt ships in your client bundle. Anything that needs server-side access to your full dataset (the MCP server, future REST clients) uses a separate server key.

Initialization

Initialise the SDK once at app startup. In Next.js this goes in your root layout or _app.tsx; in React, in your top-level component.

Basic setup

Import the SDK
import {
  init,
  initClickTracking,
  initPageTracking,
  initLocationTracking,
} from "@adtivity/adtivity-sdk";
Initialise inside useEffect
useEffect(() => {
  if (typeof window === "undefined") return;
  if (window.__ADTIVITY_BOOTSTRAPPED__) return;
  window.__ADTIVITY_BOOTSTRAPPED__ = true;

  const API_KEY = process.env.NEXT_PUBLIC_ADTIVITY_API_KEY;
  if (!API_KEY) {
    console.error("Adtivity SDK: API key is not configured");
    return;
  }

  init({
    apiKey: API_KEY,
    debug:  false,
    // Optional tuning:
    // batchSize: 10,
    // flushInterval: 5000,
  });

  initPageTracking();
  initClickTracking();
  initLocationTracking();
}, []);

Configuration options

OptionTypeDefaultDescription
apiKeystringRequired. Your project key from Settings → API Keys.
apiBaseUrlstringAdtivity defaultOverride the backend endpoint.
debugbooleanfalseLogs all SDK activity to the console. Use during development.
batchSizenumber10Events to collect before an automatic flush.
flushIntervalnumber5000Milliseconds between automatic flushes.
maxRetriesnumber3How many times to retry a failed batch.
retryDelayMsnumber1000Base delay for exponential backoff retries (doubles each attempt).
collectDatabooleantrueMaster switch — set false to start with all tracking off.

Click Tracking

Once initClickTracking() is running, Adtivity listens for any element marked with a data-adtivity-* attribute. No onClick handlers, no manual track() calls.

General click tracking

Use data-adtivity-track on any clickable element.

html
<div data-adtivity-track="feature-card-click">
  Click me
</div>

Buttons

For <button> elements, use the more specific data-adtivity-button-track.

jsx
<Button data-adtivity-button-track="web3-simulate-token-transfer">
  <Rocket className="mr-2 h-5 w-5" />
  Simulate Token Transfer
</Button>

Links

For navigation, use data-adtivity-link-track.

jsx
<Link href="/cars" data-adtivity-link-track="header-nav-cars">
  <Car className="mr-2 h-4 w-4" />
  Cars
</Link>

Custom properties

Attach arbitrary JSON with data-adtivity-props.

html
<button
  data-adtivity-button-track="add-to-cart"
  data-adtivity-props='{"productId": "123", "price": 49.99}'>
  Add to Cart
</button>
💡
Use descriptive track namessignup-button-click is far more useful in your dashboard (and to your AI agent) than btn1.

Page Tracking

Once initPageTracking() is running, Adtivity fires a “Page Viewed” event automatically. Duplicate URLs are deduplicated — if the URL has not changed, no event fires. Not available in React Native.

TriggerWhen it fires
Initial loadWhen the user first lands on your site.
history.pushStateClient-side navigation in React Router, Next.js App Router, etc.
history.replaceStateURL replacement without adding a history entry.
popstateBrowser back / forward navigation.

Properties captured on every page view:

PropertyDescription
pageTitledocument.title
pathwindow.location.pathname
querywindow.location.search
fullUrlwindow.location.href

Location Tracking

Calling initLocationTracking() enriches every event with geolocation derived from the visitor's IP address — country, region, city. No browser permission prompt; it's resolved server-side.

FieldDescription
countryISO country code, e.g. “US”.
regionState or province.
cityCity-level location.
ip_addressVisitor's public IP address.

These fields are promoted to top-level in the API payload. Works in both browser and React Native.

Identity

The SDK gives you three layers of identity: anonymous ID (free), session ID (free), and user ID (one identify() call). Together they let Adtivity stitch a complete journey from first visit through sign-in and beyond.

Anonymous ID

An auto-generated UUID stored in localStorage, created the first time a visitor hits any page where the SDK is initialised. It persists across sessions, so a returning visitor on the same browser keeps the same anonymous ID.

Automatic
// Automatically handled by the SDK.
// No code needed — created on first visit.

Session ID

A separate identifier scoped to a single browser tab. Open your site in a new tab and you get a new session ID; close the tab and that session ends.

Automatic
// Automatically handled by the SDK.
// New session per tab/window.

User ID (custom)

When a user signs in, call identify(userId, properties?) with your own user ID. It is sent immediately — not batched. After this call, user_id is attached to all subsequent events for the session.

After sign-in
import { identify } from "@adtivity/adtivity-sdk";

identify("user_12345", {
  email:      "user@example.com",
  plan:       "pro",
  signupDate: "2025-01-01",
});

Web3 / wallet identity

Use setWallet(address, chainId?) when a user connects a wallet. Both fields are automatically included on every subsequent event — trackEvent, identify, and trackTx alike. Pass null to clear on disconnect.

On wallet connect
import { setWallet, identify } from "@adtivity/adtivity-sdk";

setWallet("0x742d35Cc...", "1");  // address, chainId
identify("0x742d35Cc...");        // use wallet as user ID

// On disconnect
setWallet(null);

Common chainId values: “1” Ethereum · “137” Polygon · “56” BNB Chain · “8453” Base · “42161” Arbitrum.

Tracking blockchain transactions

Use trackTx(name, properties?) for on-chain transactions.transaction_hash and contract_address are promoted to top-level fields in the API payload (not nested inside properties).

On transaction confirmed
import { trackTx } from "@adtivity/adtivity-sdk";

trackTx("NFT Minted", {
  transaction_hash:  "0xdef...789",
  contract_address:  "0x123...456",
  token_id:          "42",
  price_eth:         "0.08",
});

Auto-Captured Data

Every event Adtivity sends — page view, click, identify — is automatically enriched with the following context. You don't need to attach any of it manually.

GroupFields
Time & URLISO 8601 timestamp · current URL with query · referrer
DeviceUser agent · browser · device type · OS
LocationCountry · region · city · anonymised IP (needs initLocationTracking)
IdentityAnonymous ID · session ID · user ID & wallet (if identify'd)
ElementElement ID · text · tag · href · CSS classes · form values (for click events)

Events

An event is a single thing that happened — a page view, a click, an identify call, a wallet connect. Every event captured by the SDK gets enriched with the auto-captured context above and lands in your Adtivity workspace ready to query.

You don't compose events manually. The SDK produces them from data attributes on your markup and from the init* functions you call once at startup.

Companies

A company is the workspace that owns your data. One Adtivity account can have multiple companies — useful if you ship more than one product, or want a clean split between staging and production. Each company has its own API key and dashboard.

Set up a new company from Settings → Companies → New.

Users

A user is anyone whose journey Adtivity has stitched together. On first visit they exist as an anonymous ID; the moment you call identify() with a userId, email, or wallet address, anonymous activity gets merged into the known user record. See Identity for how to wire that up.

Lifecycle

Adtivity automatically classifies users by where they sit in your funnel — visitor, signup, activated, paying, churned — by reading the events you're already sending. The Lifecycle Chart on your dashboard is the canonical view; the same buckets are queryable through the MCP server.

Stripe Integration

Connect Stripe from Settings → Connections — about 90 seconds. Once connected, MRR, ARR and churn auto-populate in your dashboard and become queryable through the MCP server. No manual event tracking required for revenue.

Paystack Integration

Processing payments in Africa? Connect Paystack the same way — Settings → Connections. Stripe and Paystack can be active in the same workspace; revenue from both is unified into a single MRR view.

Wallet Monitoring — No SDK Required

You don't need the SDK to track on-chain activity. Register any wallet address in the Web3 Wallets section of your company dashboard and Adtivity monitors it at the backend level — no MetaMask, no ethers.js, no SDK integration.

Endpoint (backend)What it returns
GET /wallets/connections/{id}/analyticsTotal txns, volume, unique tokens, inflow/outflow, gas, top tokens
GET /wallets/connections/{id}/recent?hours=24Transactions in the last N hours
GET /wallets/connections/{id}/activitiesPaginated full transaction history
GET /wallets/balance?wallet_address=…&network=…Current balance and token holdings
SDK events vs wallet monitoring are separatetrackTx() and setWallet() capture user-triggered on-chain actions from your frontend. Wallet monitoring tracks the registered address itself via backend indexing — it works even if you have no SDK installed.

Privacy & Consent

Call setConsent(false) when a user opts out. This stops all future event tracking, flushes and clears the event queue, and removes persisted events from localStorage. Call setConsent(true) to re-enable.

import { setConsent } from "@adtivity/adtivity-sdk";

// User opts out
setConsent(false);

// User opts back in
setConsent(true);

You can also start with all tracking off by passing collectData: false to init().

Runtime Configuration

Swap the API key or backend URL after init — useful when users switch workspaces or when you point to a different environment at runtime.

import { setApiKey, setBaseUrl } from "@adtivity/adtivity-sdk";

// After user logs into a different workspace
setApiKey("new-api-key");

// Point to a different backend
setBaseUrl("https://your-custom-backend.com");

React Native

The SDK is React Native compatible. Because AsyncStorage reads are asynchronous, call waitUntilReady() before tracking to ensure the anonymous ID and session ID have loaded from storage.

import { init, waitUntilReady, trackEvent, setWallet } from "@adtivity/adtivity-sdk";

init({ apiKey: "your-api-key" });

await waitUntilReady();   // wait for AsyncStorage IDs to load

trackEvent("App Opened");
setWallet("0xabc...", "1");
FeatureBrowserReact Native
trackEvent
trackTx
identify
setWallet
initPageTracking
initClickTracking
initLocationTracking
waitUntilReadyno-opRequired

REST API Coming soon

A public REST surface is on the roadmap for teams that want to read Adtivity data outside of the dashboard or the MCP server — for internal tools, custom dashboards, or scheduled exports. Endpoints, auth model, and rate limits will be documented here once it lands.

Until then, the MCP server is the supported way to query your data programmatically.

SDK Reference

Quick index of every public function in @adtivity/adtivity-sdk:

ExportSignatureWhat it does
init(config) => voidInitialize the SDK. Singleton — safe to call multiple times.
trackEvent(name, props?) => voidTrack a custom event. Batched and retried automatically.
trackTx(name, props?) => voidTrack a blockchain transaction. Promotes transaction_hash and contract_address to top-level.
identify(userId, props?) => voidIdentify a user. Sent immediately, not batched.
setWallet(address, chainId?) => voidAttach wallet address and chain ID to all subsequent events. Pass null to clear.
initPageTracking() => voidEnable automatic page view tracking. Browser only.
initClickTracking() => voidEnable automatic click tracking via data-adtivity-* attributes. Browser only.
initLocationTracking() => voidEnable IP-based geolocation. Browser + React Native.
setConsent(bool) => voidEnable or disable all data collection. false flushes and clears the queue.
setApiKey(key) => voidUpdate API key at runtime.
setBaseUrl(url) => voidUpdate backend URL at runtime.
waitUntilReady() => Promise<void>Wait for async ID init. Required in React Native; no-op in browser.

Event Schema

Every event the SDK produces ships with the same envelope of auto-captured fields. The full reference is in Auto-Captured Data; the short version:

All events are sent as a JSON array to POST /sdk/event with an X-API-Key header. Top-level fields (wallet_address, chain_id, transaction_hash, contract_address, country, region, city, ip_address) are always promoted out of properties. Null and empty-string values are omitted.

{
  "type":              "track",
  "eventName":         "Token Swap",
  "timestamp":         "2025-06-23T12:00:00.000Z",

  "anonymous_id":      "uuid-v4",
  "session_id":        "uuid-v4",
  "user_id":           "user_abc123",

  "wallet_address":    "0xabc...def",
  "chain_id":          "1",

  "transaction_hash":  "0xdef...789",
  "contract_address":  "0x123...456",

  "country":           "US",
  "region":            "California",
  "city":             "San Francisco",
  "ip_address":        "203.0.113.1",

  "properties": {
    "url":       "https://app.example.com/swap",
    "referrer":  "https://app.example.com/",
    "userAgent": "Mozilla/5.0...",
    "amount":    "100",
    "token":     "USDC"
  }
}
FieldTypeDescription
typestringAlways “track”.
eventNamestringThe name you passed to trackEvent() or trackTx().
timestampISO 8601When the event fired.
anonymous_idstringPer-visitor UUID, persisted in localStorage / AsyncStorage.
session_idstringPer-tab / per-session identifier.
user_idstringSet after identify().
wallet_addressstringSet after setWallet().
chain_idstringChain ID passed to setWallet().
transaction_hashstringFrom trackTx() — promoted to top-level.
contract_addressstringFrom trackTx() — promoted to top-level.
country / region / city / ip_addressstringFrom initLocationTracking() — promoted to top-level.
propertiesobjectAll remaining custom and auto-captured fields (URL, referrer, user agent, element data).

Best practices

A few things worth doing on day one:

  • Name events for humans, not machines. Your dashboard, your team, and your AI all read these.
  • Identify users early. Call identify() the moment auth resolves so the anonymous → known stitch happens cleanly.
  • Turn on debug: true locally. You'll see every event in the console while you wire things up.
  • Keep the public key public, the server key private. They're separate by design.

Next: Connect MCP → · Plug in Stripe → · Web3 identity →