Attribution9 min readVisitTrack Team

How to Track Signups by Traffic Source Without Cookies

Capture each visit's referrer, UTMs and landing page, carry that first touch into your signup, and credit every new account to the source that earned it.

To track signups by traffic source without cookies, record where each visit came from when it lands (referrer, UTM parameters and landing page), keep that “first touch” with the signup form in your own app, and send a signup event with the first touch attached when the account is actually created. In cookieless analytics the visitor id rotates daily, so that hand-off at signup is what keeps Monday's blog visit credited for Thursday's signup instead of “Direct.”

This guide walks through why cookieless signup attribution breaks by default, the exact setup that fixes it, where the signup event should fire for each kind of signup flow, and how to read the resulting report without over-trusting small numbers.

Key takeaways

  • A traffic source is the referrer, UTM parameters and landing page of the visit that first brought someone to your site.
  • Without a stored identifier, a visitor who returns on a later day looks new, so their signup is credited to that day's source, usually Direct.
  • The fix is to capture the first touch in the browser at landing time and send it with the signup, so attribution survives without any analytics cookie.
  • Fire the signup event when your backend confirms the account was created, not when the signup button is clicked.
  • Read signups by source together with time-to-signup and what those signups do next, not as a ranking of raw counts.

Why is signup attribution hard without cookies?

Analytics tools connect a signup to an earlier visit through an identifier. With a first-party cookie or localStorage id, the same browser is recognized across days, so a signup on Thursday is linked to the blog visit on Monday that started the relationship. In cookieless mode nothing is stored on the device. The visitor is recognized only through a server-side hash that changes every day, so Thursday's visit starts from zero.

ScenarioStored first-party idCookieless (daily hash)Cookieless + first-touch hand-off
Lands from Google, signs up in the same visitGoogleGoogleGoogle
Lands from Google, signs up later the same dayGoogleGoogle (same daily id)Google
Lands from a newsletter Monday, types the URL Thursday to sign upNewsletterDirectNewsletter
Lands from Hacker News on a phone, signs up on a laptopDirect (new device)DirectDirect, unless your app links the devices

The third row is the common SaaS case: people discover you, leave, and come back to sign up when they have time. Lose it and your signup report quietly over-credits Direct and under-credits whatever actually created the demand. The mechanics of the daily hash are explained in cookieless tracking explained.

What counts as a traffic source for a signup?

Four fields describe where a visit came from. Capture all four; different questions need different ones.

FieldExampleAnswers
Referrernews.ycombinator.comWhich site sent the visit
UTM source / medium / campaigndevweekly / newsletter / oct-sponsorWhich campaign you tagged
Landing page/blog/stripe-revenue-attributionWhich piece of content made the first impression
Landed at2026-09-28T08:14:00ZHow long the path to signup took

When both exist, trust the UTM tags more: they carry your intent (“this is the October sponsorship”), while the referrer is only what the browser chose to pass on. If you're unsure how a given referrer or UTM combination will be grouped into a channel, the referrer channel checker shows the classification side by side with GA4's default channel grouping.

How do you track signups by source, step by step?

The setup below uses VisitTrack's tracker, but the pattern works with any tool that exposes the current visit's attribution: capture at landing, keep it in your own app, send it back at signup.

  1. 1.Install the script in cookieless mode (or hybrid mode, which is cookieless for EU, UK and Swiss visitors). See cookieless mode.
  2. 2.Add a hidden first-touch field to your signup form. The script fills it with the current visit's attribution as JSON, and only when it's empty, so a value saved earlier wins.
  3. 3.When the form is submitted, save that value on your own user record. It is now part of the data your signup form collects, stored in your database.
  4. 4.When the account is created, send a signup event from your server with the first touch attached.
  5. 5.Use your own stable user id as the visitor id for that event, and the same id in your payment provider's metadata, so later revenue joins the same person.
<form action="/signup" method="post">
  <input name="email" type="email" required />
  <input type="hidden" name="first_touch" data-vt-first-touch />
  <button>Create account</button>
</form>
// app/signup/actions.ts
"use server";

export async function signup(formData: FormData) {
  const user = await createUser(String(formData.get("email")));

  const raw = formData.get("first_touch");
  const firstTouch = typeof raw === "string" && raw ? JSON.parse(raw) : undefined;
  await saveFirstTouch(user.id, firstTouch); // keep it on your own user row

  await fetch("https://visitrack.app/api/track", {
    method: "POST",
    headers: {
      Authorization: `Bearer ${process.env.VISITRACK_API_KEY}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({ type: "event", visitorId: user.id, name: "signup", firstTouch }),
  });
}

The first touch only ever moves back in time: if an earlier one is already known for that visitor, the later one is ignored. The full server-side contract, including field limits and the identify call, is in send events from your server.

Multi-page visits before signup

The hidden field captures the attribution of the visit in which the form is submitted. To keep the very first visit across days without a cookie, your app can store window.visitrack.attribution() itself (in its own session, or on a lead record when someone joins a waitlist) and send that at signup instead. Whatever your app keeps is your data, so disclose it like any other form data.

Where should the signup event fire for each signup flow?

The signup event is the numerator of every signup-by-source report, so it must fire exactly once per real account. Where that is depends on how accounts are created:

Signup flowWhere to fire the eventCommon mistake
Email and password formAfter the API confirms the account (browser or server)Firing on button click, counting validation failures
Google or GitHub OAuthIn the OAuth callback, only when a new user was createdCounting returning users who log in through OAuth
Magic linkWhen the link is first redeemed and the user row is createdCounting the email request, not the redemption
Team inviteWhen the invitee accepts; usually tagged as its own sourceCrediting the invitee to the inviter's original channel
Waitlist that converts laterFire a separate waitlist event, then signup on activationMerging the two and losing the time gap

Pick one place per flow and fire from there only, or you'll double-count. The custom events docs include the OAuth pattern, which carries the visitor id through the redirect so the server-side event joins the earlier visits.

What changes once the first touch is carried into signup?

A worked, illustrative example. A B2B SaaS running cookieless gets 300 signups in a month. Before adding the first-touch hand-off, the Signups report credited them like this; after a month with the hand-off in place, with similar traffic, the split changed:

SourceWithout hand-offShareWith hand-offShare
Direct11438%5117%
Google organic8428%10535%
Newsletter sponsorships217%5418%
Hacker News / Reddit3612%4515%
X / LinkedIn279%3010%
Other referrals186%155%
Total300100%300100%
Illustrative. The total doesn't change; the credit moves from Direct to the sources that started the relationship.

The newsletter line is the interesting one. Newsletter readers often skim on a phone or during a commute and sign up days later, so same-visit attribution is especially unfair to them. Without the hand-off, the sponsorship looked like 21 signups and would probably have been cut. The trade-off between crediting the first and last visit is covered in first-touch vs last-touch attribution for SaaS.

Is carrying the first touch still privacy-friendly?

Yes, with honest framing. Nothing is stored on the visitor's device by the analytics script, and nothing follows the visitor across other sites. Your own app keeps one record of how a person found you, at the moment they choose to create an account with you, which is the same kind of data a “How did you hear about us?” field collects. Treat it like any other signup data: mention it in your privacy policy, keep it with the account, delete it when the account is deleted.

What you cannot do without an identifier is link the anonymous visits of someone who never signs up across days. That is the point of cookieless measurement, and it is why aggregate traffic reports in cookieless mode count a person who visits on three days as three daily visitors.

How do you read a signups-by-source report without fooling yourself?

  • Ignore sources with fewer than about 20 signups in the period when ranking. The difference between 6 and 9 signups is noise.
  • Look at time to signup per source. Search often converts in the same visit; communities and newsletters often take days. A source with a long lag will look bad in a short window.
  • Check signup quality. A source that brings many signups who never activate is worse than one that brings fewer who do. Use the same source split on your activation event and on revenue.
  • Compare against the landing page. A spike from one viral post is a content win, not a channel win; check which landing page the signups entered on.
  • Keep a small self-reported field. A “How did you hear about us?” question catches podcasts, word of mouth and conference talks that no referrer will ever show.

Why do so many signups still show as Direct?

Even with the hand-off, some signups will be Direct, and some of that is genuinely unknowable. The usual reasons:

  • The first visit was on another device. Unless the person logs in on both, nothing links them.
  • Apps that strip the referrer: links opened from messaging apps, email clients and many mobile apps arrive with no referrer at all.
  • Untagged links in your own channels: email footers, docs, social bios. Tag them with UTMs.
  • Visitors who typed the URL after hearing about you in a podcast, a meeting or a private chat. That is real word of mouth, recorded as direct traffic.
  • Browser privacy features or extensions that block the analytics script on the landing visit.

Direct is not a channel you can buy more of, so treat a large Direct share as a measurement gap to narrow, not a strategy.

Can you track signups by traffic source without cookies?

Yes. Capture the visit's referrer, UTM parameters and landing page in the browser, keep that first touch with the signup in your own app, and send it with the signup event. Attribution then survives even though the analytics script stores nothing on the device.

Why are most of my signups attributed to Direct?

Usually because the visitor discovered you in one visit and signed up in a later one that had no referrer, and your analytics couldn't link the two. Carrying the first touch into the signup, tagging your own links and adding a self-reported source field reduce it.

Should the signup event fire on the client or the server?

Either works if it fires only after the account is confirmed. The server is more reliable for OAuth, magic links and invites, because the account is created in a callback rather than in the page.

What is first-touch attribution for signups?

It credits a signup to the source of the person's first known visit, rather than the visit in which they signed up. For SaaS it usually reflects which channel created demand better than last touch does.

Is storing the first touch with the user GDPR compliant?

It is ordinary account data collected when a person signs up, similar to a 'how did you hear about us' field. You still need a lawful basis and a privacy-policy mention. This is general information, not legal advice.

How many signups do I need before comparing sources?

As a rule of thumb, at least 20 to 30 signups per source in the period before ranking them. Below that, look at trends over several months instead of a single period.

Keep reading

See which channels actually bring paying customers

VisitTrack is cookie-free analytics with revenue attribution built in. One script tag, no consent banner, live in two minutes. 14 days free, no card required.

14-day free trial · No card required · Cookie-free · Cancel anytime

Or explore the live demo first →