Refport
Quickstarts

React SPA (Vite)

Track referral clicks in a Vite React SPA and send leads and sales to your backend.

Prerequisites

  • A React SPA built with Vite (or any bundler)
  • A separate backend server (Node.js, Express, Next.js API routes, etc.)
  • A Refport account and API key (Settings → API Keys)

Architecture overview

In a React SPA, the browser SDK captures the click ID client-side. Lead and sale tracking must always happen server-side — never call track.lead() or track.sale() directly from the browser, as that would expose your API key.

Browser                          Your Backend
──────                           ────────────
1. User arrives via referral link
   refp_id stored in cookie

2. User signs up
   → POST /api/auth/register
     { clickId, email, ... }   → refport.track.lead()

3. User purchases
   → POST /api/checkout
     { clickId, ... }          → refport.track.sale()

Install the React SDK and add <RefportTracker /> to your app root. It reads refp_id from the URL and persists it in a cookie for 90 days.

npm install @refport/react
src/App.tsx
import { RefportTracker } from '@refport/react';
import { Router } from './Router';

export default function App() {
  return (
    <>
      <RefportTracker />
      <Router />
    </>
  );
}

Use getClickId() from @refport/react to read the current value of the refp_id cookie and include it in your API request.

src/api/auth.ts
import { getClickId } from '@refport/react';

export async function registerUser(email: string, password: string) {
  const clickId = getClickId();

  const res = await fetch('/api/auth/register', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ email, password, clickId }),
  });

  return res.json();
}

On your backend, receive the clickId from the request body and call track.lead().

server/routes/auth.ts (Express example)
import { Router } from 'express';
import { Refport } from 'refport';

const refport = new Refport({ apiKey: process.env.REFPORT_API_KEY! });
const router = Router();

router.post('/register', async (req, res) => {
  const { email, password, clickId } = req.body;

  const user = await createUser({ email, password });

  try {
    if (clickId) {
      await refport.track.lead({
        clickId,
        eventName: 'Sign Up',
        customerExternalId: user.id,
        customerEmail: user.email,
        customerName: user.name,
      });
    }
  } catch {
    /* tracking failure must never block sign-up */
  }

  res.json(user);
});

export default router;

Do the same when a purchase is completed — send the click ID from the browser or read it from the Stripe webhook client_reference_id.

src/api/checkout.ts (browser)
import { getClickId } from '@refport/react';

export async function startCheckout(priceId: string) {
  const clickId = getClickId();

  const res = await fetch('/api/checkout', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ priceId, clickId }),
  });

  const { url } = await res.json();
  window.location.href = url;
}
server/routes/checkout.ts (Express)
import { Router } from 'express';
import Stripe from 'stripe';

const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!);
const router = Router();

router.post('/', async (req, res) => {
  const { priceId, clickId } = req.body;

  const session = await stripe.checkout.sessions.create({
    line_items: [{ price: priceId, quantity: 1 }],
    mode: 'subscription',
    success_url: `${req.headers.origin}/success`,
    cancel_url: `${req.headers.origin}/pricing`,
    metadata: {
      refportExternalCustomerId: req.user.id,
      refportClickId: clickId ?? undefined,
    },
  });

  res.json({ url: session.url });
});

export default router;

Refport's webhook handler reads these metadata fields and attributes the sale automatically. See the Stripe integration guide for the full attribution fallback chain.

Server implementation guides

The backend shown above uses Express. For a full server-side walkthrough, see:

What's next

On this page