Track signups with Next.js and Auth.js (NextAuth)

Use the signIn event and its isNewUser flag so returning users are skipped.

Before you start

The Chartsy script must already be on every page of your site, including the app where signup happens - it supplies where the visitor came from; this guide only adds the email. See the installation guides.

1Add your secret key

Copy the site's secret key from Settings → Domains in Chartsy and store it as CHARTSY_SECRET_KEY in your server's environment. It never goes in browser code or git.

CHARTSY_SECRET_KEY=your_secret_key

2Add the Chartsy helper

One small file that reads the three Chartsy cookies from the request and posts them with the email. Needs Node 18+ for the built-in fetch. Details of the call are in the Identify API reference.

// chartsy.js
const readJson = (raw) => {
  try { return JSON.parse(decodeURIComponent(raw || '')) || {}; } catch { return {}; }
};

export async function chartsyIdentify(email, cookies) {
  // cookies: a function name => value (Express: n => req.cookies[n];
  // Next.js: n => cookies().get(n)?.value)
  const first = readJson(cookies('chartsy_attrib'));
  const last = readJson(cookies('chartsy_attrib_last'));
  try {
    await fetch('https://dashboard.chartsy.app/api/attribution/identify/', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        Authorization: `Bearer ${process.env.CHARTSY_SECRET_KEY}`,
      },
      body: JSON.stringify({
        email,
        attribution_first: first,
        attribution_last: Object.keys(last).length ? last : first,
        visitor_id: cookies('chartsy_visitor_id') || '',
      }),
    });
  } catch (err) {
    console.error('Chartsy identify failed', err); // never block signup on analytics
  }
}

3Identify in the signIn event

Auth.js tells you whether the account was just created with isNewUser, so returning users are skipped. Email signups and Google/GitHub logins both go through it.

import NextAuth from 'next-auth';
import { cookies } from 'next/headers';
import { chartsyIdentify } from './chartsy';

export const { handlers, auth } = NextAuth({
  // ...providers, adapter
  events: {
    async signIn({ user, isNewUser }) {
      if (!isNewUser || !user.email) return;
      const jar = await cookies();
      await chartsyIdentify(user.email, (n) => jar.get(n)?.value);
    },
  },
});

Needs a database adapter

isNewUser is only set when Auth.js uses a database adapter. Without one, call the helper from your own onboarding step instead.

Related articles

Chartsy Team

Written by

Chartsy Team

Analytics team at Chartsy

The Chartsy Team writes guides, product updates, and resources to help SaaS and eCommerce founders make sense of their metrics, without SQL or spreadsheets.

Chartsy
Ministry of Economy and Innovation
Startup Albania

The Chartsy program is realized with the financial support of the Albanian Government through the Ministry of Economy and Innovation, under the Grant 2026 scheme, and is implemented by the Innovation4Albania Agency.