From “something broke” to “we fixed it, and it worked”
Send feedback reports and alerts to Slack, Microsoft Teams or your own endpoint. Turn any problem into a Linear, GitHub or Jira issue with the context filled in. Seven days after the issue is closed, Metrickle measures whether the fix moved the metric.
Accessibility barrier reported on /checkout
“The pay button can't be reached with Tab.”
Create issue turned it into ENG-12 in Linear. Seven days after it closed, task success for keyboard users went from 41% to 78%.
Hear about problems where you already work
Add a Slack incoming webhook, a Microsoft Teams workflow or your own HTTPS endpoint to any app, and choose what goes there. Alerts are checked every hour and sent once a day at most, so an ongoing problem doesn't post every hour.
When a release went out in the two days before an alert, the message names it. That's often the cause.
| Event | When it's sent | Webhook type |
|---|---|---|
| Feedback reports | Every “Report a problem” submission. Accessibility barriers get their own headline and list the reporter's accessibility settings. | feedback.created |
| Task success drops | A saved task's success rate over the last 24 hours is at least 15 points below its 7-day baseline, with enough attempts on both sides. Names the assistive-tech group doing worst. | alert.task_success_drop |
| New friction hotspots | An element, form or page started causing rage, dead or error clicks, u-turns or form errors in the last 24 hours, and wasn't a hotspot the week before. | alert.new_hotspot |
| Fix results | Seven days after a linked issue is closed: the metric before vs after. | issue.measured |
- Visitor text stays text. A feedback message can't ping a Slack channel or add links in Teams.
- A delivery log for every destination, with failures flagged at the top of the Integrations page.
- Retried when it fails: network errors, timeouts and 5xx responses are tried twice more.
- Slack and Teams URLs are treated as secrets: only owners and admins add them, and they're shown masked.
Turn a problem into an issue in one step
Connect Linear, GitHub Issues or Jira Cloud once for the workspace with an access token, then pick a team, repository or project for each app. “Create issue” on a feedback report, a friction hotspot or a saved task opens a draft you can edit before it's sent.
The draft brings the context a developer needs: the page, platform and accessibility settings, where attempts stopped, the friction in abandoned attempts, the hardest-hit assistive-tech group, and the last seven days' numbers.
- Tokens are encrypted at rest and never shown again after you connect.
- Checked when you connect: you see whose token it is before anything is created.
- The reporter's words are quoted literally, so an “@someone” in feedback doesn't notify anyone.
- Any member can file an issue; only owners and admins connect accounts.
| Issue | Metric | Before → after |
|---|---|---|
| ENG-12 Pay button unreachable by keyboard | Checkout task success | 41% → 78% |
| #48 Rage clicks on plan toggle | Sessions hitting it | 6.2% → 0.4% |
| WEB-7 Coupon field errors | Similar reports | 9 → 1 |
Measured over the 7 days before an issue was opened and the 7 days after it was closed.
Know whether the fix worked
Every issue created from Metrickle records its metric for the seven days before it was opened. Metrickle checks the issue every few hours; seven days after it's closed as done, it measures the same thing again and shows the result on the Fixes page, and in Slack, Teams or your webhook if you choose “Fix results”. Issues closed as not planned aren't measured.
| Created from | Metric | Better when it goes |
|---|---|---|
| A saved task | Task success rate | Up |
| A friction hotspot | Share of sessions hitting that element or form | Down |
| A feedback report | Reports in the same category on the same page | Down |
Mark every release
Each app has a deploy hook URL. Call it from CI, or point a GitHub, Vercel or Netlify webhook at it, and every production release appears as a marker on the Overview chart, with the same list in text under the chart. New app versions seen in your events are added automatically, which suits iOS, Android and Flutter apps.
# Copy the URL from Integrations → Releases → Deploy hook
curl -X POST "$METRICKLE_DEPLOY_HOOK" \
-H "content-type: application/json" \
-d '{"version": "2.4.0", "description": "Checkout fixes"}'
| Sender | Recorded as a release | Ignored |
|---|---|---|
Any CI step (curl) | A JSON body with version, and optionally description, url and environment. Or ?version= in the URL. | Requests with no version |
| GitHub webhook | Published releases (tag name), and successful deployment statuses | Pings, drafts, pre-releases, failed and preview deployments |
| Vercel webhook | Deployment succeeded, production target (short commit SHA) | Preview deployments |
| Netlify outgoing webhook | Deploy succeeded (short commit SHA) | Deploy previews and branch deploys |
Webhook reference
Generic webhooks receive a JSON POST with the event type in metrickle-event and a unique id in metrickle-delivery. Any 2xx response counts as delivered.
Every request is signed with the secret shown when you added the webhook. metrickle-signature is t=<unix ms>,v1=<hex>, where the hex is an HMAC-SHA256 of the timestamp, a full stop and the raw body. Reject requests more than five minutes old.
content-type: application/json
metrickle-event: feedback.created
metrickle-delivery: evt_…
metrickle-signature: t=1790841234000,v1=5f2c…
{
"id": "evt_…",
"type": "feedback.created",
"createdAt": 1790841234000,
"app": { "id": "app_…", "name": "Orbit Web" },
"url": "https://app.metrickle.com/apps/app_…/feedback",
"data": {
"category": "accessibility",
"accessibilityBarrier": true,
"message": "The pay button can't be reached with Tab",
"path": "/checkout",
"a11y": ["keyboard"]
}
}
import { createHmac, timingSafeEqual } from "node:crypto";
// header: t=<ms>,v1=<hex HMAC-SHA256 of "<t>.<raw body>">
export function verify(rawBody, header, secret) {
const { t, v1 } = Object.fromEntries(header.split(",").map((p) => p.split("=")));
if (Math.abs(Date.now() - Number(t)) > 5 * 60_000) return false;
const expected = createHmac("sha256", secret).update(`${t}.${rawBody}`).digest("hex");
return v1?.length === expected.length && timingSafeEqual(Buffer.from(expected), Buffer.from(v1));
}
Common questions
Which plans include integrations?
All of them, including Free: Slack, Teams and webhooks, issue trackers, fix results and release markers. Task success alerts and issues from tasks need Task analytics, which comes with Growth and up.
Do I need to install an app in Slack, Linear, GitHub or Jira?
No. Slack and Teams use an incoming webhook or workflow URL. Linear, GitHub and Jira use an access token you create in the tracker: a Linear personal API key, a GitHub fine-grained token with Issues read and write, or an Atlassian API token with your account email. One-click sign-in for trackers is planned.
How are tracker tokens stored?
Encrypted with AES-256-GCM before they're saved, and never returned by the API or shown again. Disconnecting an account deletes its token; the issues it created stay in your tracker.
Will alerts flood our channel?
No. Alerts are checked hourly; each task alert is sent at most once a day and each hotspot at most once a week, and you choose which events each destination gets.
Does it work with Jira Data Center or GitHub Enterprise Server?
Not yet. Jira Cloud (atlassian.net) and GitHub.com are supported today.
See where your apps break, and who they break for
Free to start. One script tag on the web, one SDK on mobile, and no cookie banner in cookieless mode.
Start tracking for free