Mixpanel Activation + HubSpot Lifecycle Stage Mismatch: Daily Stuck-User Alert to Slack via n8n

Activated in Mixpanel, still 'Lead' in HubSpot — here's how to catch those users daily before they go cold.

The flow
Mixpanel logo
Source
Mixpanel
HubSpot logo
Process
HubSpot
n8n logo
Process
n8n
Slack logo
Destination
Slack

The stack in the order it runs — data flows from the source through to where it lands.

Why this stack

The actual pain: when a user completes activation but nobody updates their lifecycle stage in HubSpot, they fall into a gap. Sales thinks CS has them. CS thinks they're in a nurture sequence. Neither is true. That gap is where churn starts, quietly.

n8n is the right tool because the set-difference math — users in Mixpanel's activation event but not in HubSpot's 'Customer' stage — runs inside a JavaScript Function node on your own infrastructure. No user data leaves to a third-party automation cloud. If you're operating under GDPR, self-hosted n8n is the correct call over Zapier or Make.

Mixpanel's Query API (JQL or the Export API) lets you pull users who fired a specific event inside a date window. HubSpot's Contacts API lets you filter by lifecycle stage. The join key is email — it has to exist as an `email` property on your Mixpanel events, or as a `distinct_id` that maps to a HubSpot contact ID. If that mapping isn't there, this playbook breaks before step 3.

One tradeoff to know upfront: if your activation event fires on anonymous users who identify later, you'll get false positives. Only run this on events fired post-identification. Check your Mixpanel `$identify` call timing before you build anything. And skip this entirely if HubSpot is not your lifecycle stage source of truth — if that lives in Salesforce or Notion, replace the HubSpot query step accordingly.

The stack (4)

  1. Mixpanel logo

    Product analytics for events and funnels.

    The export/query API turns product metrics into scheduled reports you push to chat.

  2. HubSpot logo

    CRM + marketing for go-to-market.

    Pipeline data becomes an automatable input for revenue reports.

  3. n8n logo

    Self-hostable workflow automation.

    Own your data and run unlimited steps without per-task pricing.

  4. Slack logo

    Team chat where most ops alerts and reports land.

    The default place a small team already lives — pipe reports here instead of email nobody opens.

How it runs

  1. 1

    Create an n8n Cron workflow

    In your n8n instance — self-hosted or n8n.cloud — create a new workflow. Add a Schedule Trigger node set to `0 9 * * 1-5`: 9 AM, weekdays only. Name it `activation-lifecycle-mismatch-alert`. Weekday-only is intentional. Nobody acts on a Saturday Slack ping about lifecycle mismatches, and daily noise trains your team to ignore the channel.

  2. 2

    Query Mixpanel for activated users in the last 24 hours

    Add an HTTP Request node. Method: POST. URL: `https://mixpanel.com/api/2.0/jql`. Set Basic Auth with your Mixpanel service account credentials. Body: a JQL script that queries for distinct users who fired your activation event — e.g., `setup_complete` — in the last 24 hours. The JQL should return an array of objects with `distinct_id` and `email` properties. Set the Content-Type header to `application/x-www-form-urlencoded`. The response is a JSON array — store it as `activatedUsers`.

  3. 3

    Query HubSpot for contacts already past 'Lead'

    Add a second HTTP Request node. Method: POST. URL: `https://api.hubapi.com/crm/v3/objects/contacts/search`. Bearer token: your HubSpot private app token. Body: a filter requesting contacts where `lifecyclestage` is IN `['customer', 'opportunity', 'salesqualifiedlead']`. Request properties `email` and `lifecyclestage` in the `properties` array. Paginate up to 100 results — increase `limit` if your active contact list exceeds 100. Store as `hubspotAdvancedContacts`.

  4. 4

    Compute the mismatch set in a Function node

    Add a Function node. Extract emails from `hubspotAdvancedContacts` into a Set for O(1) lookup. Iterate over `activatedUsers` and collect every user whose email is NOT in that Set — those are your activated-but-not-updated contacts. Return an array `mismatchedUsers` with each user's email, Mixpanel distinct_id, and event timestamp. If `mismatchedUsers.length === 0`, set a flag `noMismatches = true`. That flag is what kills the empty-state Slack noise downstream.

  5. 5

    Branch: skip if no mismatches

    Add an IF node checking `noMismatches === true`. True routes to a No-op node and terminates. False continues to the Slack step. Don't post a 'nothing to report' message daily — that's how you train your team to ignore the channel. The IF node is not optional.

  6. 6

    Format the Slack message

    Add a Function node to build the Slack Block Kit payload. Header block: `🚨 Activated users not updated in HubSpot — [date]`. Section block: list each mismatched user as `• user@email.com — activated at [timestamp]`. Cap at 10 entries and append `...and N more` if the array runs longer. Include a direct link to the HubSpot contacts filtered view so the CS rep can act in one click without digging.

  7. 7

    Post to Slack #cs-ops channel

    Add a Slack node — n8n has a native integration. Authenticate with your Slack bot token, created in api.slack.com with `chat:write` scope. Set channel to `#cs-ops` or `#activation-alerts`. Post the formatted Block Kit payload. Set `unfurl_links: false` to keep the message clean. Tag the on-call CS lead with `<@UXXXXXXXXX>` in the header block — there needs to be a named owner on every alert, not just a channel notification.

  8. 8

    Optional: auto-update HubSpot lifecycle stage

    After the Slack post, add a HubSpot node to PATCH each mismatched contact's `lifecyclestage` to `salesqualifiedlead`. URL: `PATCH https://api.hubapi.com/crm/v3/objects/contacts/{contactId}` with body `{properties: {lifecyclestage: 'salesqualifiedlead'}}`. Do not enable this step until you've run the workflow for 5 days and confirmed the mismatch logic is clean. Premature auto-updates corrupt CRM data and, once your team loses trust in the system, you won't get it back easily.

Want me to build this for you instead?

Product Audit and CTO Mode run out of this same thinking. If you’re reading this thinking “I want this, but in my product” — let’s talk.

See services

More like this