Email reports

A report is the same thing the dashboard shows, pushed instead of pulled: the period's metrics with a comparison against the previous period, the top ranked things to fix with their evidence, the worst JS errors by session reach, web vitals at p75, and your busiest pages.

Turning it on

Per project, under Settings → Email reports. Choose weekly (the default), daily, or off, and optionally send to an address other than your account address - a team alias works well. Send me a test report builds a real report from your real data and mails it immediately, so you can see exactly what will arrive.

A project that has never received a single event is skipped: there is nothing to report and an empty report every week is worse than none. Once a project has history, a period with no traffic still sends - a sudden zero is itself the news.

What the timing means

  • Weekly covers the last 7 days and compares against the 7 before it.
  • Daily covers the last 24 hours and compares against the day before.
  • Reports go out after the insight engine runs, so today's findings are in today's mail rather than tomorrow's.
  • Each project is rate-limited by its own last-sent timestamp, and the send is claimed before it is built - so however often the scheduler fires, and however many replicas run it, you get one report per period.

Self-hosting: the mail backend

Betterloop sends through whichever backend is configured. Set one of these and restart:

# Resend - an HTTP API, nothing to install
RESEND_API_KEY=re_...
EMAIL_FROM=Betterloop <reports@yourdomain.com>

# ...or any SMTP server (Gmail app password, SES, Postmark, your own)
SMTP_URL=smtps://user:app-password@smtp.gmail.com:465
EMAIL_FROM=Betterloop <reports@yourdomain.com>

With neither set, nothing is sent - but every attempt is still written to the delivery log with the reason, so a misconfigured deployment shows up in the UI instead of failing silently. The delivery log lives at the bottom of the project's Settings page and records the last few sends with the provider's own error text on any failure.

The From address must be on a domain your provider has verified. Resend accounts can use onboarding@resend.dev before attaching a domain, which is enough to prove the pipeline works.

Other mail we send

  • A welcome message at signup with the three steps to first data.
  • Password resets: a single-use link that expires in an hour and revokes every existing session when used.

That is the complete list. No drip sequences, no re-engagement mail, no announcements you did not ask for.

Related: Slack digests · pulling the same findings into Claude Code