AI integration prompt

A self-contained prompt to paste into Cursor, Claude Code, v0, or any AI editor with your app's repo open. It wires uReferrals attribution through your Stripe Checkout flow — frontend fetch + backend metadata forwarding — in about two minutes of the AI's time.

Signed in as a builder? Open any program → the persistent Install-tracking card has a “Copy AI integration prompt” button that pre-fills your publishable key + cookie domain automatically. This public page uses placeholders so you can share the recipe without leaking a tenant's key.

How to use it

  1. Open your target app's repo in an AI-capable editor.
  2. Copy the prompt below and paste it into the AI chat.
  3. Replace uref_pk_YOUR_PUBLISHABLE_KEY with your program's real key (grab it from the uReferrals dashboard → Programs → your program).
  4. Replace .YOURDOMAIN.com with your parent domain (keep the leading dot).
  5. Let the AI make the changes. It should confirm which architecture pattern (single-app vs split-app) it detected before writing code.
  6. Set the env var on every deployed environment and rebuild. Run the verification checklist at the end of the prompt.
Add uReferrals affiliate attribution to this app's Stripe Checkout flow.

═══════════════════════════════════════════════════════════════════════════
CONTEXT (read this first, don't skip)
═══════════════════════════════════════════════════════════════════════════

uReferrals is a first-party referral tracking service. Attribution works
in three steps:

  1. Visitor arrives at the marketing site with ?ref=<code> in the URL.
     A small tracker script reads the ref and stores it in a cookie
     called _uref on the domain.

  2. Visitor navigates to checkout — often on a different subdomain
     (e.g. marketing at YOURDOMAIN.com, app at app.YOURDOMAIN.com).
     For the cookie to follow, it must be scoped to the parent domain
     ".YOURDOMAIN.com" — the tracker's data-cookie-domain attribute
     handles this.

  3. When the visitor clicks "Buy" / "Upgrade", the app reads the cookie
     back via window.uReferrals.metadataPayload() and passes the ref to
     its own backend, which forwards it into stripe.checkout.sessions
     .create({ metadata: { ur_affiliate_ref: ... } }).

  4. Stripe fires checkout.session.completed to uReferrals. We verify
     the signed webhook and credit the affiliate. No client-side
     conversion posting — the browser is never trusted for money-affecting
     events.

CRUCIAL: this repo may be split across TWO apps — one for marketing (where
the ref lands) and one for the checkout app (where the ref is read at
purchase time). If so, the tracker must be installed on BOTH so the cookie
is set on marketing and readable on the app. The tracker no-ops when no
cookie is present, so putting it on the app is free.

═══════════════════════════════════════════════════════════════════════════
ARCHITECTURE DETECTION (do this before coding)
═══════════════════════════════════════════════════════════════════════════

Look at the repo layout. Report which of these it matches:

  Pattern A — Single app: marketing pages + checkout page live in one
              Next.js/Remix/etc app under the same domain.
  Pattern B — Split apps: apps/marketing (or similar) and apps/web (or
              similar) — marketing has a pricing page that deep-links to
              a separate checkout app.

You'll install the tracker snippet in slightly different places based on
this. Don't guess — grep for "stripe.checkout.sessions.create" to find
the checkout backend, and for pricing/upgrade CTAs to find the marketing
side. Confirm the layout in your response BEFORE writing code.

═══════════════════════════════════════════════════════════════════════════
WHAT TO DO
═══════════════════════════════════════════════════════════════════════════

────────────────────────────────────────────────────────────────────────
STEP 1 — Wire the publishable key via env var (do this in every app that
         will host the tracker)
────────────────────────────────────────────────────────────────────────

Rather than hard-coding the publishable key, read it from a public env
var so the same code works across dev/staging/prod without edits:

  NEXT_PUBLIC_UREFERRALS_KEY=uref_pk_YOUR_PUBLISHABLE_KEY

Add this line to each app's .env.example (so future developers see it)
and to .env / .env.local for local dev. In deployed environments (VPS,
Vercel, Cloudflare Pages, wherever this app runs), the operator sets it
there directly.

If your framework isn't Next.js, use its equivalent build-time env
convention (VITE_UREFERRALS_KEY for Vite, REACT_APP_UREFERRALS_KEY for
CRA, etc). The key MUST be exposed to the client — it's a "publishable"
key, safe in the browser.

────────────────────────────────────────────────────────────────────────
STEP 2 — Install the tracker in every app that shares the domain
────────────────────────────────────────────────────────────────────────

In each app's root layout (Next.js App Router: apps/*/src/app/layout.tsx
— OR similar), inject the tracker in <head>. Guard on the env var so
missing config skips the tag entirely:

  {process.env.NEXT_PUBLIC_UREFERRALS_KEY && (
    <script
      async
      src="https://api.ureferrals.com/t/tracker.js"
      data-key={process.env.NEXT_PUBLIC_UREFERRALS_KEY}
      data-cookie-domain=".YOURDOMAIN.com"
    />
  )}

For the checkout app (Pattern B) this is REQUIRED, not optional — the
window.uReferrals global must exist on the app for metadataPayload() to
work at checkout time. The tracker no-ops if no cookie is present, so
the cost is one small async script per page load.

────────────────────────────────────────────────────────────────────────
STEP 3 — Frontend: read the tracker payload at checkout
────────────────────────────────────────────────────────────────────────

Find the code that calls this app's /billing/checkout (or equivalent)
endpoint. Right before the fetch, read the tracker payload:

  const meta =
    (typeof window !== 'undefined' &&
      (window as any).uReferrals?.metadataPayload?.()) || {}

Then include it in the request body:

  await fetch('/api/checkout', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ ...existingFields, metadata: meta }),
  })

The tracker returns { ur_affiliate_ref: "<10-char-code>" } when a
referral cookie is present, or {} otherwise. Both are safe — Stripe
just gets no extra metadata when there's no ref.

The optional chaining guards against the tracker script not having
loaded yet (rare — GTM slow, ad blocker, race on first paint). Don't
crash the buy button on that edge case.

────────────────────────────────────────────────────────────────────────
STEP 4 — Backend: forward the ref into the Stripe session
────────────────────────────────────────────────────────────────────────

Find the route handler that calls stripe.checkout.sessions.create().
Extract the incoming metadata safely — whitelist just our key, don't
pass arbitrary client input through to Stripe:

  const clientMeta = (req.body?.metadata || {}) as Record<string, unknown>
  const referralRef = typeof clientMeta.ur_affiliate_ref === 'string'
    ? clientMeta.ur_affiliate_ref.slice(0, 500)
    : undefined

Then spread it into the session's metadata alongside whatever this app
already tracks (userId, plan, etc):

  const session = await stripe.checkout.sessions.create({
    // ... existing fields (mode, line_items, customer, etc) ...
    metadata: {
      // ... existing keys ...
      ...(referralRef ? { ur_affiliate_ref: referralRef } : {}),
    },
  })

Preserve every existing metadata field. Only add ur_affiliate_ref when
it's present in the request.

═══════════════════════════════════════════════════════════════════════════
BOUNDARIES (what NOT to do)
═══════════════════════════════════════════════════════════════════════════

  ✘ Don't add any package to package.json — this is pure fetch + <script>
  ✘ Don't post conversions from the client — Stripe's webhook is the
    only trusted source. Ignore any "window.uReferrals.convert()" method
    if you see it referenced elsewhere; that's the legacy spoofable path.
  ✘ Don't set the cookie yourself — the tracker owns _uref.
  ✘ Don't call any uReferrals API from the server — the sessions.create
    metadata is the entire integration.

═══════════════════════════════════════════════════════════════════════════
HUMAN STEPS (for the person running the AI editor to do OUTSIDE the code)
═══════════════════════════════════════════════════════════════════════════

  1. If you don't have a uReferrals program for this app yet:
     • Sign in at https://app.ureferrals.com
     • Programs → + New Program → name it after this app
     • Open the created program → grab the publishable key
       (starts with uref_pk_)

  2. Set NEXT_PUBLIC_UREFERRALS_KEY in every deployed environment:
     • Local dev: add to .env / .env.local
     • Prod / staging: add to the VPS/Vercel/Cloudflare env config
     • Value: uref_pk_YOUR_PUBLISHABLE_KEY
     (If you're an AI reading this, remind the human to also do this
     step. Without it, the tracker skips itself and no attribution
     happens even after your code changes.)

  3. Rebuild + redeploy each app after setting the env var.
     NEXT_PUBLIC_* values in Next.js are inlined at build time — a
     runtime env change alone won't take effect. Trigger a fresh build.

═══════════════════════════════════════════════════════════════════════════
VERIFICATION (run these AFTER deploy to confirm the loop works)
═══════════════════════════════════════════════════════════════════════════

  1. Open an incognito browser window.
  2. Visit https://api.ureferrals.com/t/<any-affiliate-code> — should
     302 to your marketing site with ?ref=<code> in the URL.
  3. DevTools → Application → Cookies → confirm _uref is set with
     Domain=.YOURDOMAIN.com.
  4. Navigate to your app's pricing / upgrade page and click through
     to checkout — the cookie should still be visible in DevTools on
     that page (proves cross-subdomain scoping works).
  5. Complete checkout — test card 4242 4242 4242 4242 in TEST mode,
     or a real small charge in LIVE mode.
  6. Stripe Dashboard → Payments → the newest → Checkout Session →
     Metadata should show BOTH:
       • whatever your app already tracks (userId, plan, etc)
       • ur_affiliate_ref = <10-char-code>
  7. Within ~10 seconds, that conversion appears in your uReferrals
     dashboard under the affiliate whose code you used.

If step 6 shows metadata but step 7 doesn't happen, the issue is on
uReferrals' end (webhook signing secret or connect setup). If step 6
shows no ur_affiliate_ref, the issue is on this app — usually step 3
missed the cookie because the tracker isn't on the app, or step 4 dropped
it (accidentally overwriting instead of spreading metadata).

Prefer a plugin?

For WordPress + WooCommerce sites, use the plugin instead — no code changes required. Grab it from your builder dashboard: Programs → any program → “Download WordPress plugin.”

Everything else (Shopify, static sites, custom stacks) works with either the AI prompt above or by installing the tracker snippet directly via Google Tag Manager — the “Add to Google Tag Manager” button on the same page handles that in one click.