Back to the growth library
PLGIntegrations

Mixpanel Signup Enrichment: Making Group Analytics Actually Mean Something

How PLG teams feed enriched company and ICP data into Mixpanel profiles and Group Analytics so cohorts, funnels, and account-level reports reflect fit, not just plan tier.

Growth team reviewing a Mixpanel-style analytics dashboard on a laptop screen

Mixpanel's group analytics only work if you feed them company data

Mixpanel's pitch has always been event-first: track what a user does, then slice it a dozen ways. Group Analytics extended that to the account level, letting you query behavior by company instead of by individual distinct_id. It's one of the more useful things Mixpanel ships that Amplitude treats as a paid add-on.

The catch is that Group Analytics is only as good as the group key you feed it. Most implementations set company_domain from a signup form field, if they set it at all, and never touch it again. A user signs up with a personal Gmail address, the group key comes back empty, and every account-level report from that point on quietly excludes them. Nobody notices until someone tries to build a "retention by company size" report and half the rows say undefined.

The fix isn't a Mixpanel setting. It's making sure a real company gets resolved and attached to the user's profile, and to a group, before the first meaningful event fires. Groful resolves the company, scores ICP fit, and surfaces relevant teammates at signup; this post is about getting that specifically into Mixpanel's profile and group model. For the enrichment fundamentals, start with the PLG signup enrichment guide.

What breaks without it

Picture a funnel report: signup → first project created → invited a teammate → upgraded. Mixpanel will happily chart the conversion rate at each step. What it won't tell you, without company context, is whether the drop-off between "first project" and "invited a teammate" is concentrated in solo users who were never going to invite anyone, or in five-person startup teams who hit friction in the invite flow.

Split that same funnel by ICP fit or company size band and the story usually changes. A 12% step conversion rate might really be 28% for your target segment and 4% for everyone else. Optimizing the blended number means shipping fixes that don't move the segment that pays. This is the same logic behind PLG activation scoring and account scoring: behavioral data needs a fit label sitting next to it, or every report is an average of two different populations pretending to be one.

Wiring enrichment into Mixpanel

Mixpanel gives you two places to put enriched data: the user profile (people.set) and a group profile (groups.set), tied together by a group key you define, usually company_domain or company_id.

Set the profile and the group together, at signup

Resolve enrichment once, right after signup, and write both the individual profile and the group profile in the same step. Waiting until a later login means early funnel events land without company context and never get it back.

const Mixpanel = require("mixpanel");
const mixpanel = Mixpanel.init(process.env.MIXPANEL_TOKEN);

const enrichment = await fetch("https://api.groful.co/v1/enrichment/lookup", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    Authorization: `Bearer ${process.env.GROFUL_API_KEY}`,
  },
  body: JSON.stringify({ externalId: userId, email }),
}).then((res) => res.json());

const domain = enrichment.company?.domain ?? "unknown";

mixpanel.people.set(userId, {
  "Company Domain": domain,
  "Company Size Band": enrichment.company?.employeeCountBand ?? "unknown",
  "Job Title": enrichment.user?.jobTitle ?? "unknown",
  "ICP Fit": enrichment.company?.icpFit ?? "unknown",
  "ICP Confidence": enrichment.company?.confidence ?? "low",
});

mixpanel.groups.set("company_domain", domain, {
  "Industry": enrichment.company?.industry ?? "unknown",
  "Employee Count": enrichment.company?.employeeCount ?? null,
  "ICP Fit": enrichment.company?.icpFit ?? "unknown",
});

mixpanel.track("Signup Enriched", {
  distinct_id: userId,
  $group_key: "company_domain",
  $group_id: domain,
});

If enrichment fails or times out, still call people.set() with whatever you have and skip the group write rather than blocking the signup flow on a third-party call.

Register the group key before you rely on it

Group Analytics needs the group key declared in your Mixpanel project settings before queries against it will work. This is a one-time setup step, but it's easy to skip if the person wiring the SDK isn't the same person with admin access to the project. Confirm company_domain (or whatever key you pick) shows up under Group Analytics in project settings before you build reports on top of it.

Backfill existing profiles with the Engage API

For an app with existing users, loop through your user table, resolve enrichment for anyone missing it, and push updates through Mixpanel's Engage API (the same people.set and groups.set calls, run as a batch job) rather than waiting for stale profiles to update themselves. Rate-limit the batch job against both Mixpanel's import limits and your enrichment credit budget.

Keep the property list short

Six or seven profile properties and three or four group properties is enough for most reporting needs: domain, size band, industry, fit tier, confidence, job title, and a routing lane if you use one. Mixpanel's Lexicon gets harder to maintain and query performance gets worse once dozens of raw enrichment fields get treated as first-class properties. Store the full enrichment payload in your warehouse and join it in there when an analysis needs more depth than the dashboard does.

Reports worth building once fit is in Mixpanel

Funnel conversion by ICP fit tier. Same funnel, same steps, segmented by fit instead of shown as one blended line. This is usually the single most useful chart to build first.

Group-level retention. With company_domain registered as a group key, Mixpanel's retention reports can run at the account level instead of the individual level, which matters more for team products where one person churning doesn't mean the account churned.

Insights by company size band. Compare feature usage or event frequency across size bands to catch onboarding flows that work for 10-person teams and stall out for 200-person ones.

Flows filtered by confidence tier. Low-confidence enrichment tends to cluster around shared inboxes and disposable domains. If those users also show unusual drop-off patterns in Flows, that's a data quality problem worth chasing before assuming it's a product issue.

Where this breaks if you skip a step

Writing to people.set without writing to groups.set. These are separate calls against separate objects in Mixpanel. Setting the individual profile property doesn't populate the group profile, and a lot of implementations stop at the first one, then wonder why Group Analytics reports come back empty.

Treating an unresolved domain as a bad-fit company. A signup that hasn't finished enriching yet and a signup that resolved to a genuinely low-fit company are different states. Keep unknown distinct from low in both the property values and the cohort definitions built on top of them, or the low-fit segment fills up with cases that are really just pending.

Re-enriching on every session. Company data doesn't change every login. Cache the result and refresh on a schedule, weekly is usually enough, rather than calling the enrichment API and rewriting Mixpanel profiles on every page load.

Forgetting the group key registration step. SDK calls will succeed silently even if the group key was never registered in project settings, and the reports built on top of it just won't have a Group Analytics option available. Check this first if a group report is missing entirely rather than just underpopulated.

A short rollout plan

Days 1–3: Wire the enrichment call and the people.set / groups.set pair into the signup flow, register the group key in project settings, and confirm both profile and group properties show up correctly in Mixpanel's user lookup for a handful of test accounts.

Days 4–7: Run the backfill job against existing users through the Engage API, then rebuild your core funnel and retention reports as fit-segmented versions.

Week 2: Swap the blended funnel and retention charts your team checks weekly for the fit-segmented ones, and start using group-level reports in account review conversations instead of individual profile lookups.

Group Analytics is the feature. Enrichment is what makes it work.

Mixpanel already built the account-level reporting layer most teams ask an analytics vendor for. What's usually missing isn't the tool, it's a company on the other end of the group key that's real, current, and scored for fit. Once that's in place, funnels, retention, and group reports stop needing a caveat about "well, this mixes free-tier tire-kickers with real accounts."

Groful is built for growth managers who need that resolution done at signup, not reconstructed later from a CSV export and a lot of VLOOKUPs. Review the PLG signup enrichment solution, check pricing, or contact Groful to scope a Mixpanel integration for your product.

Turn this playbook into workflow

Enrich signups, score ICP fit, and surface expansion opportunities with Groful.