NextAuth (Auth.js) Signup Enrichment: A PLG Playbook for SaaS Growth Teams
How SaaS teams enrich NextAuth and Auth.js signups, resolve company context from OAuth and email sign-in, score ICP fit, and route product-led opportunities without touching the auth flow.
NextAuth gives you an identity, not a customer profile
NextAuth, now developed under the Auth.js name, is the default choice for a huge share of Next.js apps that need sign-in without building their own session and provider logic. It handles Google, GitHub, email magic links, credentials, and a dozen other providers behind one callback, and it does that job well. What it doesn't do, and was never meant to do, is tell you anything about the business behind the person who just signed in.
A session.user object from NextAuth is usually an email, a name if the provider supplied one, and maybe an avatar URL. That's enough to log someone in. It's not enough to know whether the account belongs to a solo developer testing your product on a Saturday or a director of growth at a 400-person company who's about to bring in four teammates. Every PLG team ends up asking the same question a few months after launch: who are these people, really, and which of them deserve more attention than a generic onboarding email?
That's the gap NextAuth signup enrichment fills. You keep the sign-in flow exactly as it is (nobody wants a company-size dropdown between them and the product) and enrich the session in the background once it exists. Groful builds this as an async workflow layered on top of an existing PLG signup enrichment pipeline: resolve the account, score it, hand the result to whichever system decides what happens next.
Where enrichment actually plugs into Auth.js
Auth.js exposes a signIn event and a session callback, and both are reasonable places to touch enrichment, but they're not interchangeable. The signIn event fires once, server-side, right after a user authenticates. That's where the enrichment call should start, because it's the one place you can be sure the event happens exactly once per new session. The session callback runs on every session read, including page loads and client-side session checks, so calling out to a third-party API there is a bad idea. Use it to read enrichment results back into the session object once they exist, not to trigger new ones.
A workable pattern looks like this:
signInevent fires, and the app writes a signup or session-start record to your database if the user is new.- That write enqueues an enrichment job: a queue message, a database row a cron picks up, or a direct call to an enrichment API from a server-only code path.
- The job resolves company, role, and confidence, then writes the result back to the user record.
- On the next session read, the
sessioncallback attaches whatever enrichment fields you want available to the client, or the app reads them server-side when it renders onboarding.
The point of splitting it this way is that authentication and enrichment have different reliability requirements. Auth needs to be fast and can't wait on a third-party lookup. Enrichment can take a few seconds, or run as a second pass an hour later once you've seen some product usage, without blocking anyone from reaching the product.
The problem with provider data alone
It's tempting to assume the OAuth provider already solved this. If someone signs in with a Google Workspace account tied to acme.com, you know the domain. That part is true and worth using: a corporate Google or Microsoft OAuth signup is one of the cheapest, highest-confidence enrichment triggers around, because the domain comes straight from the identity provider instead of a guess.
The gap is everyone who doesn't sign in that way. Email magic links go to whatever address someone typed in. A large share of B2B signups never touch a corporate OAuth provider at all: freelancers checking out a tool on their personal address, people using a company Gmail alias instead of their real work domain, evaluators who deliberately avoid connecting a corporate account to a new vendor. Enrich only when Google Workspace or Microsoft shows up and you'll systematically under-resolve a chunk of the funnel, and it won't be a random chunk. It tends to skew toward exactly the cautious, security-conscious users who are often the better fit.
This is why NextAuth enrichment needs the same personal email enrichment path that any signup flow needs: name, email pattern, and any product-side signals (workspace name, invited-by user, teammates already at the company) feeding a resolution process that returns a confidence score, not a guess dressed up as a fact.
Provider-aware enrichment routing
Not every NextAuth signup needs the same amount of enrichment work. Splitting by provider and email type keeps you from spending enrichment credits on records you can resolve for free, and from under-investing in the ones that actually need it.
Corporate Google or Microsoft OAuth. Domain is already known with high confidence. Skip domain guessing entirely and go straight to firmographic lookup: company size, industry, funding stage. Cheap and fast.
GitHub OAuth. A decent signal if the account has a public email or an organization affiliation, weaker otherwise. Worth checking, not worth over-trusting on its own.
Email magic link on a personal domain. The hard case. Route through name and pattern-based resolution, and treat the output as a confidence-scored guess until product behavior (workspace name, teammate invites) corroborates it.
Email magic link on a work domain, where someone typed a company email but there's no OAuth provider attached. Same firmographic lookup as the Google or Microsoft path, since the domain itself is the strong signal.
Credentials provider. Whatever your own signup form collected is your only signal beyond the email. Treat it the same as a magic-link signup on that domain.
Building this branching logic once, at the point where you decide what to enrich and how deeply, saves you from either enriching everyone at the deepest (and most expensive) tier or skipping the users who actually need the deeper pass.
Keep confidence and fit as separate numbers
A mistake we see often in early NextAuth enrichment setups: teams collapse "we're confident about this company match" and "this company is a good fit for us" into one field, usually called something like leadScore. That single number then gets used to trigger sales alerts, and it goes wrong in both directions. A confidently resolved but low-fit signup, a student, a competitor doing research, a company well outside the target size, triggers noise. A genuinely promising account with a lower-confidence match gets ignored because the score looks unremarkable.
Keep them separate. Store an enrichment confidence score and an ICP fit score as two distinct fields, and let your routing rules combine them explicitly:
- High confidence, high fit → this is the one that should actually interrupt someone. Route to sales-assist or a founder-led follow-up once there's product usage to back it up.
- High confidence, low fit → resolved correctly, just not your customer. Leave in self-serve, don't spend outbound effort here.
- Low confidence, high signal from other sources (teammate invites, workspace name matching a known ICP account) → worth a review queue rather than either an alert or a discard.
- Low confidence, low signal → don't act on it yet. Re-check after more product usage accumulates rather than guessing now.
A minimal enrichment schema for a NextAuth app
You don't need a wide table to start. A practical first version stores, per user:
userId, tied to whatever NextAuth's adapter uses as the primary key.authProvider: google, github, email, credentials, and so on.emailDomainType: corporate or personal, determined at write time.resolvedCompanyDomain, nullable until enrichment completes.enrichmentConfidence, a 0 to 1 or low/medium/high value.icpFitScore, kept separate from confidence, as above.role,seniority,companySize: the fields you'll actually use for onboarding personalization or routing, nothing collected "just in case."enrichedAt, so you know how stale the record is and can re-run enrichment after significant product usage.
Resist the urge to store every field an enrichment provider returns. Each additional field is something your team has to trust, maintain, and explain when someone asks why a user got routed a certain way.
Checklist before shipping
- Enrichment triggers from the server-side
signInevent, never from client code, and API keys never reach the browser. - OAuth-provided domains (Google Workspace, Microsoft) skip guesswork and go straight to firmographic lookup.
- Personal-domain and magic-link signups go through resolution with confidence, not silent guessing.
- Confidence and ICP fit are stored as separate fields and combined explicitly in routing rules.
- Re-enrichment triggers exist for records with low initial confidence, once there's more product behavior to work with.
- Someone on the team can explain, for any given routed record, exactly which fields and thresholds produced that outcome.
Where enrichment earns its keep
The value shows up downstream, not in the enrichment call itself. A resolved, high-fit NextAuth signup can get an onboarding checklist tuned to their role instead of a generic tour. A magic-link signup that turns out to work at a known target account can trigger teammate discovery instead of getting treated as a lone free user. An account that never resolves with any confidence can stay in self-serve indefinitely without wasting anyone's time trying to sell to it.
None of that requires touching the auth flow. NextAuth stays exactly as fast and simple as it is today, and enrichment runs alongside it, feeding the growth and sales-assist decisions that auth data alone was never going to answer. Groful runs this as a managed workflow across signup enrichment, ICP scoring, and product-led sales routing. See pricing, read more on the blog, or get in touch if you want to map your NextAuth or Auth.js signup events into a working enrichment pipeline.
Turn this playbook into workflow
Enrich signups, score ICP fit, and surface expansion opportunities with Groful.
Published
Sep 7, 2026
Reading Time
8 min read
Tags
Nextauth-signup-enrichment, Authjs-signup-enrichment, Plg-signup-enrichment, Icp-scoring, Product-led-sales
Sections
- NextAuth gives you an identity, not a customer profile
- Where enrichment actually plugs into Auth.js
- The problem with provider data alone
- Provider-aware enrichment routing
- Keep confidence and fit as separate numbers
- A minimal enrichment schema for a NextAuth app
- Checklist before shipping
- Where enrichment earns its keep
