# Gate-check usage data (/use-cases/research/user-insights)



<Callout type="info">
  **The Verifier Gate (SOP §6)**: before a number or a status claim ships, it has to clear four checks. **Definition gate**: real people, not visitors (a raw unique-visitor count runs several times higher than genuine humans); "active" means someone who actually did something, not someone who passively received a message; paid means a real invoice, not a tracking pixel that might be broken; region means the account's own time zone, not a spoofable IP. **Source gate**: confirmed and inferred stay in separate columns. Something overheard in a DM is not consensus, and anything short of hard evidence gets labeled "unconfirmed" instead of quietly getting promoted to fact. **Self-verification gate**: a "0" or a wild swing gets proven to be real before it's reported as a finding. The query gets checked for a broken filter or an empty join before the number is trusted. **Status gate**: "the automation is running" requires a schedule ID and a run history to point to; "we're planning to build this" never gets written as "this is already running."
</Callout>

Copy this prompt to start your first task:

<Prompt>
  Set up a daily check on our growth metrics — lock down what "active" (someone who actually did something, not passive) really means, catch suspicious zeros or wild swings before they get reported, cross-check numbers against a second source, and post a trustworthy daily summary in #growth.
</Prompt>

<LivePreview component="NewThread" scenario="{ draft: &#x22;Set up a daily check on our growth metrics — lock down what \&#x22;active\&#x22; (someone who actually did something, not passive) really means, catch suspicious zeros or wild swings before they get reported, cross-check numbers against a second source, and post a trustworthy daily summary in #growth.&#x22; }" />

## What is this workflow? [#what-is-this-workflow]

Gate-checking usage data means hiring a Data Analyst teammate that acts as your growth data hub and verifier, not just someone who runs a query and pastes the result. It produces a daily growth digest — real DAU, core active, new signups, and paid — cross-checked against a second source before any of it gets written down, plus a channel-attribution report that lists every real source instead of just the two or three channels someone remembered to check. An anomaly scan stays silent by default and only speaks up when something has actually moved, and a "still-alive" heartbeat line runs even on a boring day, so a quiet automation reads as "nothing changed" instead of "silently stopped running."

## How to use this workflow [#how-to-use-this-workflow]

<Steps>
  <Step>
    ### Hire a Data Analyst: write the bio to match this role, not the generic template [#hire-a-data-analyst-write-the-bio-to-match-this-role-not-the-generic-template]

    Open **AI Teammates** in the sidebar, click **Hire AI Teammate**, and pick the **Data Analyst** template. The template's default bio describes connecting evidence to decisions in general. Replace it on the Profile step so the teammate starts out already knowing it's the verifier, not just the one who runs the query:

    <Prompt>
      You're our growth data hub and verifier, not just a number-puller. Before any number ships, lock the definition (real people vs. visitors, active vs. passive), cross-check it against a second source, and never call an automation 'running' without a schedule ID and a run record. If a number looks off, prove the query isn't broken before reporting it as a finding.
    </Prompt>

    Confirm the name and click **Create teammate**. They land in their own channel, which is where you'll send everything below. [More on hiring →](/ai-teammates/hire-an-ai-teammate)

    <LivePreview component="CreateAssistantPage" scenario="{ focus: &#x22;profile&#x22;, initialState: { start: &#x22;template&#x22;, templateRef: &#x22;@helio/data-analyst&#x22;, name: &#x22;Data Analyst&#x22;, bio: &#x22;You're our growth data hub and verifier, not just a number-puller. Before any number ships, lock the definition (real people vs. visitors, active vs. passive), cross-check it against a second source, and never call an automation 'running' without a schedule ID and a run record. If a number looks off, prove the query isn't broken before reporting it as a finding.&#x22; } }" />
  </Step>

  <Step>
    ### Connect the sources that answer different questions [#connect-the-sources-that-answer-different-questions]

    The SOP is explicit that these are separate truth sources, not one dashboard: behavioral analytics answers "who visited and clicked," the business database answers "what did they actually do," and the billing ledger answers "what did they actually pay." Mixing them up is exactly how "visitors" gets reported as "users." Add PostHog, Amplitude, or MongoDB from the skills marketplace (all three are real, installable Helio skills, not a hypothetical connector), plus whatever query access your own warehouse or event table needs. The paid numbers in the daily digest need the billing side connected too — query access to wherever billing actually lives (the billing database, a warehouse table, or a regular Stripe export), because none of the behavioral tools above can answer "what did they actually pay." [Skills & Plugins →](/connect/skills-and-plugins)

    <LivePreview component="AssistantSkills" />

    The attribution table (which UTM or KOL link actually drove a signup) is a different kind of source again, and it usually lives in Notion. Connect that as a Tool under **Integrations** instead of a skill, since Notion is a native connector. [Connect your tools →](/connect/connect-tools-to-ai-teammates)
  </Step>

  <Step>
    ### List every real source, not the two or three someone remembers [#list-every-real-source-not-the-two-or-three-someone-remembers]

    The attribution table only means something if it's actually complete. A channel report that only checks the sources someone thought to look at just launders a partial picture into a confident-sounding number:

    <Prompt>
      Which channel actually drove the most signups last month?
    </Prompt>

    <LivePreview
      component="AssistantChat"
      scenario="{ assistantName: &#x22;Data Analyst&#x22;, messages: [
    { author: &#x22;user&#x22;, text: &#x22;Which channel actually drove the most signups last month?&#x22; },
    { author: &#x22;assistant&#x22;, text: &#x22;Pulled every UTM-tagged link and KOL-tracking entry from the attribution table, not just the channels usually checked. Organic search led at 34%, but the second-highest was a KOL link nobody had been tracking as a real channel, at 19%. Nine signups came in with no attribution tag at all, flagging those separately rather than folding them into any one channel's number.&#x22; },
  ] }"
    />
  </Step>

  <Step>
    ### Stay quiet by default, and prove a quiet day isn't a broken one [#stay-quiet-by-default-and-prove-a-quiet-day-isnt-a-broken-one]

    The point of a heartbeat isn't the alert, it's the absence of one. Nothing crossing a threshold should look identical from the outside to an automation that's still actually running:

    <Prompt>
      Anything from the anomaly scan today?
    </Prompt>

    <LivePreview
      component="AssistantChat"
      scenario="{ assistantName: &#x22;Data Analyst&#x22;, messages: [
    { author: &#x22;user&#x22;, text: &#x22;Anything from the anomaly scan today?&#x22; },
    { author: &#x22;assistant&#x22;, text: &#x22;Checked at 8am, nothing crossed a threshold today: DAU, signups, and paid are all within normal range of the last two weeks. No alert needed, but logging this heartbeat so a quiet day doesn't read the same as a scan that silently stopped running.&#x22; },
  ] }"
    />
  </Step>

  <Step>
    ### Turn it into a daily growth digest: require honesty when it fails [#turn-it-into-a-daily-growth-digest-require-honesty-when-it-fails]

    The digest posts to `#growth`, and a teammate can only post in channels it's a member of — open `#growth` and add this teammate before turning the schedule on. Then open **Automations** in the sidebar, click the **Create via Chat** dropdown, and pick this teammate:

    <Prompt>
      Every day at 8am, pull real DAU, core active, new signups, and visitor UV from behavioral analytics, and real new paid, repeat, and existing paid from billing. Compare each to yesterday and to the same day last week. Cross-check the headline number against a second source before you write it down. Post a conclusion-first daily digest to #growth, then, if a public dashboard is already set up, refresh it with de-identified aggregates only. If you can't pull the data or can't post, report the failure and why. Never report success you didn't actually have. On a day where nothing changed, still post one line with a timestamp, so a quiet day and a silently broken automation don't look the same from the outside.
    </Prompt>

    <LivePreview component="NewThread" scenario="{ populated: false }" />
  </Step>
</Steps>

**Querying your data sources and posting the digest run on their own:** pulling from analytics, billing, and the attribution table is a read action, and posting to a channel this teammate already belongs to doesn't reach outside Helio or leave anything irreversible, so this flow doesn't wait on your approval. See [Control](/ai-teammates/control) for what does pause for sign-off.

<Callout type="info">
  If reports should stay aggregated and de-identified (no real names, emails, or individual sessions), put that in the teammate's instructions, and spot-check the output before sharing it more widely.
</Callout>

## Tips for Better Results [#tips-for-better-results]

| Tip                                                      | Description                                                                                                                                                                                |
| -------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Lock the definition before pulling a number              | "Active" means someone who did something, not someone who passively received a message, and paid means a real invoice, not a tracking pixel. Settle this before the query runs, not after. |
| Keep confirmed and inferred in separate columns          | Something overheard in a DM isn't consensus. Anything short of hard evidence gets labeled "unconfirmed" instead of quietly being promoted to fact.                                         |
| Prove a suspicious zero before reporting it              | A "0" or a wild swing gets checked for a broken filter or an empty join before it ships as a finding, not after.                                                                           |
| Require a schedule ID before calling something "running" | "The automation is running" needs a schedule ID and a run history to point to. "We're planning to build this" is a different claim and never gets written as if it's already live.         |

## Common Questions [#common-questions]

<Accordions type="single">
  <Accordion title="What makes this different from just running a query and pasting the number?">
    Every number clears the Verifier Gate first: locked definitions, a cross-check against a second source, and proof a suspicious zero isn't a broken query, before it's ever reported as a finding.
  </Accordion>

  <Accordion title="What counts as active in the daily digest?">
    Someone who actually did something, not someone who merely received a message. A raw unique-visitor count runs several times higher than genuine active users, so the digest keeps the two separate.
  </Accordion>

  <Accordion title="How does the channel-attribution report avoid missing sources?">
    It's built from every UTM-tagged link and KOL-tracking entry in the attribution table, not just the two or three channels someone remembered to check. Signups with no attribution tag get flagged separately instead of folded into any one channel's number.
  </Accordion>

  <Accordion title="Why does the automation post something even on a day nothing happened?">
    Because a quiet automation and a silently broken one look identical from the outside otherwise. The heartbeat line with a timestamp is what proves it's still actually running.
  </Accordion>

  <Accordion title="Can this teammate call an automation running without evidence?">
    No. The Status gate requires a schedule ID and a run history before that claim ships — "we're planning to build this" never gets written as "this is already running."
  </Accordion>
</Accordions>

<Cards>
  <Card title="Research" href="/use-cases/research" description="Back to the research use case overview." />
</Cards>
