Skip to content
DocsAlerts, brief and pings

Reading the numbers

Alerts, the Monday brief and new-customer pings

The five alert rules and when they fire, what the Monday brief contains, and how to send new-customer pings to Slack or Discord.

Joinsight tells you about your numbers in three ways. Alerts fire when something broke or moved enough to need a look. The Monday brief is a short weekly summary. New-customer pings tell you each time someone starts paying, with the page and channel that brought them. All three read the same pre-computed numbers as the dashboard and the MCP server, so an alert, the brief and a question in Claude never disagree.

Alerts are meant to be rare. Each rule has a threshold and a minimum size, so one churned customer or three fewer signups in a quiet week stays silent. When a rule does fire, it names the cause. That cause is computed by code, mostly by the same diff engine behind explain_change in the MCP server. It is never guessed by a model.

How alerts are checked

Joinsight evaluates the five rules for every workspace once an hour, and again right after each recompute, which follows any sync that brought in new data. Each rule fires at most once per calendar day in the workspace's time zone, which you set under Settings → General. If the condition still holds the next day, it can fire again, so a problem you haven't fixed doesn't go quiet on its own.

The windows below use complete UTC calendar days, like every number in Joinsight. "The last 7 days" means the 7 days ending yesterday, and "the previous 4 weeks" means the 28 days before those. Comparing one week with the average of the four before it smooths out the week-to-week noise that a straight week-over-week comparison would alert on.

Money thresholds are in your reporting currency. Where this page says €50, read 50 units of whatever currency the workspace reports in.

The five rules

MRR drop

Fires when churn spikes.

  • Trigger: churned MRR in the last 7 days is more than twice the weekly average of the previous 4 weeks, and at least €50.
  • Minimum: at least 2 customers churned in those 7 days. One large customer leaving is a conversation to have, not a trend.
  • Title: "Churn is up: €X MRR lost in 7 days".
  • Cause: the plan, billing source, first-touch channel and first landing page that account for most of the churned MRR, each compared with its own weekly average. The sentence reads like "€640 MRR churned in the last 7 days across 5 customers, against a weekly average of €180. Most of it was on Pro monthly (€420), from Organic search · Google, first landing on /pricing."
  • Links to: Revenue.

Signup drop

Fires when fewer people sign up than usual.

  • Trigger: signups in the last 7 days are at least 30% below the weekly average of the previous 4 weeks.
  • Minimum: the weekly average must be at least 10 signups. Below that, a 30% swing is normal variation.
  • Title: "Signups down X% in the last 7 days".
  • Cause: the channel that fell the most and up to two landing pages that lost the most signups. For those pages, it also compares Search Console clicks over the two most recent complete weeks, shifted back 3 days because Search Console data arrives late. It checks snippet sessions against their weekly average too.
  • Snippet check: if the snippet has sent no events for 24 hours, the alert says so: "The snippet has stopped sending events, which can look like a drop." A broken install and a real drop look the same on a chart, and the fix is very different.
  • Links to: Content & channels.

Signups are counted from identify() calls, so this rule only works once identify() runs at signup.

Money page slipping

Fires when a page that earns money loses ground in Google.

  • Which pages: the 10 pages with the most attributed MRR from customers whose first payment fell in the last 90 days. Pages with no attributed MRR are ignored.
  • Trigger: comparing the latest complete Search Console week (ending 3 days ago) with the week before, the page lost at least 3 positions in average position, or at least 30% of its clicks.
  • Minimums: the position check needs at least 100 impressions in the earlier week, and the clicks check needs at least 20 clicks. Both stop a page with a handful of impressions from bouncing in and out of the alert.
  • Title: "/your-page is slipping in search". When several pages slip, the alert is about the one carrying the most MRR.
  • Cause: the positions and clicks lost, the page's attributed MRR, and up to three queries that lost the most position, weighted by impressions. Only queries with at least 10 impressions in both weeks count. For example: "/blog/stripe-vs-paddle lost 3.4 positions (6.2 to 9.6) week over week, and it carries €310 MRR. Biggest losses: "stripe vs paddle" (4.1 to 8.3)."
  • Links to: Content & channels.

The filter is the point of this rule. A page slipping from position 6 to 9 is worth your morning only if it brings in paying customers, and this rule only looks at pages that do.

Failed payments

Fires when past-due MRR jumps.

  • Trigger: MRR on past-due subscriptions today is more than twice its daily average over the previous 28 days, and at least €50.
  • Title: "Failed payments: €X MRR past due".
  • Cause: up to three plans where past-due MRR grew most compared with 7 days ago, and the most common decline reasons on subscriptions that are past due now, when the billing source records them: Stripe's decline code on the latest invoice, or RevenueCat's billing issue reason.
  • Links to: Revenue.

Past-due MRR is still counted in MRR until the subscription cancels. A rise here usually comes before a churn spike, which is why it gets its own rule. The MRR drop checklist covers what to do next.

Data health

Fires when a source needs you.

  • A connection was revoked: "Stripe access was revoked. Reconnect it to resume syncing."
  • A connection has failed to sync for 24 hours or more.
  • App Store Connect stopped the analytics report request.
  • The Instagram token expires within 7 days, or has expired.
  • The snippet has sent no events for 24 hours, once it has sent at least one.

The title is the first issue, followed by "and N more" when there are several. This is the only rule with a direct fix link: it goes to Connections, where each source shows its own error. A sync error under 24 hours old stays quiet, so a short outage that the next sync clears doesn't wake you up.

Where alerts appear

  • In the app. The Overview shows up to three alerts from the period you're viewing at the top of the screen. Each one opens in place to show the cause, and data-health alerts have a "Fix this" link.
  • By email. Each alert is emailed to every member of the workspace, with the subject "Workspace name: alert title" and a button to the relevant screen ("Fix it" for data health, "See the details" otherwise). Each member gets their own copy, so nobody sees the other members' addresses.
  • In Slack or Discord, if you added a webhook (see below). The post has the title, the sentence and the link.
  • Through MCP. get_alerts_and_health returns recent alerts with the sentence and the full computed cause, including any annotations in the window.

The demo workspace never sends emails or webhook posts. A workspace that is locked because its trial or subscription ended isn't checked at all, so nothing fires until a plan is active again.

How the sentence is written

Every rule builds a plain sentence from a template: the numbers, the contributors and the labels. That template is always valid on its own.

When the Joinsight server has an Anthropic API key configured, Claude may rephrase that sentence to read better. What it receives is the pre-formatted facts (totals, plan names, channel labels, page paths, search queries) and the template sentence. Nothing that looks like an email address is sent, as a final check. Claude is told to use only the facts given and to copy numbers exactly.

The reply is then checked in code. It is thrown away, and the template used instead, if it contains any number that isn't in the facts, runs over 45 words, uses an exclamation mark or an em dash, or doesn't come back within a few seconds. Without an API key, the template is used as is. The model only ever writes the sentence. It never decides whether an alert fires or what caused it.

The Monday brief

The brief is a short email that covers the previous week, Monday to Sunday. It goes out on Monday at 08:00 in the workspace's time zone, which you set under Settings → General. It stays under 200 words, and every number in it links to the screen it comes from.

A typical brief has four parts.

The headline. MRR at the end of the week and its change from the week before: "MRR €6,420, +€180 (+2.9%) vs last week." If you also sell once (Stripe payments outside subscriptions, RevenueCat non-renewing purchases), the week's one-time sales follow: "One-time sales: €640 from 12 payments." A workspace that only sells once gets revenue in MRR's place, as on the Overview: "Revenue €1,200 from 14 one-time sales, +€300 (+33%) vs last week." The subject line carries the same numbers.

What changed. Up to three changes, picked from new MRR, churned MRR, one-time revenue, signups, Search Console clicks and snippet sessions. They are ranked by relative change, and each metric must reach a minimum size first: €10 for new or churned MRR or one-time revenue, 5 signups, or 20 clicks or sessions in either week. Each line gives the before and after, then the cause: "Mostly Organic search · Google (+€90) and /blog/stripe-vs-paddle (+€60)." One-time revenue is explained by product first: "Mostly Lifetime deal (+€240)." If you added an annotation during the week, it is quoted: "On 14 Oct: Raised Pro to €39."

Search Console data lags by about 3 days, so the brief shifts both search weeks back 3 days to compare two complete weeks. That line is labeled with its end date, for example "Search clicks to 9 Oct".

Do this week. One suggestion, chosen in this order:

  1. The largest revenue leak from Money found, when it's worth at least €10 a month and puts more MRR at stake than a slipping money page: "Move 14 customers off old prices: the current prices would add €168 MRR." Annual-plan candidates are never the action.
  2. Otherwise, if a page that earns money is slipping in search (the same check as the alert), refresh it: "Refresh /blog/stripe-vs-paddle: it lost 3.4 positions and carries €310 MRR."
  3. Otherwise, the top keyword opportunity. That's a query where you rank between positions 8 and 20, on a page that already earned organic revenue in the last 90 days, ranked by impressions × the page's revenue per click: "Improve /pricing for "paddle alternative": it ranks 11.2 with 2,400 impressions, and the page earned €480 MRR in 90 days."
  4. If none exists, the section is left out.

The suggestion is deliberately one item. A list of ten ideas gets skimmed and none of them get done. The post on striking-distance keywords explains why positions 8 to 20 are where a refresh pays off.

Goal and attribution. If you set an MRR goal, how far along you are and the estimated date you reach it. Then the attributed share over the last 4 weeks: how much of new MRR Joinsight could link to a first touch, with the customer counts. A workspace that only sells once gets the share of first-time buyers linked to a first touch instead. That line keeps the rest of the brief honest about how much it can see.

The "What changed" sentences can be rephrased by Claude under the same rules as alerts. If the rephrased version would push the brief to 200 words or more, the template sentences are used instead.

Preview and turn it off

Settings → Notifications has a "Preview this week's brief" link. It shows the email exactly as it is sent, in HTML and plain text, with its word count. Use it to check the brief before Monday, or after you change the goal or add annotations.

To stop the brief, the workspace owner clears "Email the Monday brief to every member at 08:00" under Settings → Notifications. The brief goes to every member of the workspace, each in their own email, and this switch turns it off for all of them. There is no per-member setting. It is separate from the switch for alert and ping emails.

The brief is skipped for a workspace with no MRR, no one-time sales that week and nothing that changed, which is usually one where billing isn't connected yet. It is never sent for the demo workspace, or while the workspace is locked because its trial or subscription ended.

New-customer pings

A ping is one line per new paying customer:

New €29/mo customer, from /blog/stripe-vs-paddle via Google

It gives the customer's MRR at first payment, the first page they landed on and the channel that brought them. For organic search it names the search engine. When no first touch is known, it says "source unknown". It never includes the customer's email or name, so a ping can go to a shared Slack channel without leaking customer data.

Pings are sent after a recompute, so they arrive shortly after the payment reaches Joinsight. Stripe syncs every 15 minutes. RevenueCat purchases arrive within a minute through its webhook, or otherwise with the daily customer sync.

Two rules keep pings from turning into noise:

  • Only recent customers. A customer is pinged only if their first payment was in the last 2 days. When you first connect Stripe and import two years of history, or a recompute links an older customer, they are marked as pinged without a message.
  • At most 20 per run. If more than 20 new customers arrive in one run, the 20 most recent are sent and the rest are marked as pinged.

All the customers from one run arrive together: one email per member with every line (subject "New €29/mo customer…" for one, "3 new customers" for several), and one Slack or Discord post. The email follows the same switch as alert emails.

While a workspace is locked because its trial or subscription ended, no pings are sent. Customers who start paying in that time follow the 2-day rule once a plan is active, so you don't get a backlog of old pings.

Slack and Discord

Alerts and pings can be posted to a Slack channel, a Discord channel or both. The Monday brief is email only.

Slack: create an incoming webhook for the channel in your Slack workspace, then copy its URL. It starts with https://hooks.slack.com/services/.

Discord: in the server's settings, open Integrations, then Webhooks, create a webhook for the channel and copy its URL. It starts with https://discord.com/api/webhooks/.

Paste the URL into "Slack webhook URL" or "Discord webhook URL" under Settings → Notifications and choose "Save notifications". Joinsight only accepts https URLs on Slack's or Discord's own domains. The URLs are stored encrypted, and the form never shows them again. It only notes, under each field, that a webhook is saved.

Each webhook is kept until you change it. Pasting a Slack URL replaces the stored Slack URL and leaves Discord as it is, and the reverse. A blank field keeps what is stored. To delete one, choose "Remove Slack webhook" or "Remove Discord webhook". Posts are plain text, and Discord posts can't ping anyone. If Slack or Discord rejects a post, Joinsight logs it and moves on. It doesn't retry, so a deleted webhook fails silently until you replace it.

Turning notifications off

Everything is under Settings → Notifications. Only the workspace owner can change it.

WhatSettingWho receives it
Alert emails and ping emails"Email alerts and new-customer pings to every member"Every member
Monday brief"Email the Monday brief to every member at 08:00"Every member
Slack and Discord postsWebhook URLs, or "Remove Slack webhook" and "Remove Discord webhook"The channel

Turning off emails doesn't stop alerts from firing. They still appear on the Overview, through MCP and in Slack or Discord if you added a webhook. The footer of every alert, ping and brief email points back to these settings. The switches apply to the whole workspace: a member can't opt out of the emails on their own.

For how each number in an alert is defined, see metric definitions. For the screens the alerts link to, see Read the dashboard.