SSO is 4th by requests but 1st by revenue
SSO came from 9 customers in 90 days, 4th by count, but they pay $3,100 MRR, more than any other request, and it holds up 2 open deals worth $40,000. Dark mode leads by count with $620 MRR behind it.
Monthly: 90 days of feature requests from support and Discord, ranked by the MRR of the customers asking and the open deals they hold up.
Reads
You get
The card on the right is a sample. Yours shows your own numbers and updates in place every run.
What lands on your board
SSO came from 9 customers in 90 days, 4th by count, but they pay $3,100 MRR, more than any other request, and it holds up 2 open deals worth $40,000. Dark mode leads by count with $620 MRR behind it.
A feature request list sorted by count favors whoever writes in most: free users, small accounts, the regulars in Discord. The request that three of your biggest customers raised once each, and that two open deals mention, sits near the bottom of it.
Once a month the agent groups 90 days of requests from Intercom and Zendesk (and Discord, counted but not priced), matches each requester to their Stripe MRR and their open HubSpot deals, and ranks the requests both ways. Product managers see where count and revenue disagree; support and founders get a list they can answer customers from.
Intercom: POST /conversations/search with created_at > the Unix time 90 days ago, plus tag_ids IN [<feature request tag>] if you tag them, and GET /conversations/{id} for the messages and source.author.email. Zendesk: GET /api/v2/search.json?query=type:ticket created>90days tags:feature_request (your tag), then GET /api/v2/users/show_many?ids=<requester_ids> for emails.
For a feature-requests forum channel, list threads with GET /channels/{channel.id}/threads/archived/public and GET /guilds/{guild.id}/threads/active, keep those started in the 90 days (the thread ID is a snowflake that encodes the time) and read each starter message. Discord does not give bots members' emails, so these are counted but carry no revenue unless you keep a username-to-email list.
Map each request to one name on the feature list the person keeps, using its synonyms; read untagged conversations too, since many requests arrive inside a support question. Propose a new name only for a cluster of 3 or more unmatched requests. Count unique requesters per feature, not conversations, so a customer who wrote five times counts once.
Stripe: GET /v1/customers/search?query=email:"<email>", then the customer's active subscriptions for MRR (monthly, after discounts). HubSpot: POST /crm/v3/objects/contacts/search with email IN [...], then POST /crm/v4/associations/contacts/deals/batch/read and the deals' amount and hs_is_closed, keeping open ones.
Join on the lowercased requester email; when it misses, match the email domain to a Stripe customer or HubSpot company domain, never free-mail. A company with several requesters adds its MRR and each deal once per feature. Requesters with no Stripe customer count in the request total and add $0. Rank by MRR, show the count rank beside it, and call out any feature whose MRR rank is 3 or more places above its count rank.
With BRIEFKIN_TOKEN set, the agent sends the result as one card that updates in place every run. Without it, you get the report in the chat.
Pick your agent, where the data comes from and how to schedule it; the commands below follow.
One command. It puts the SKILL.md in ~/.claude/skills and in ~/.agents/skills, which Codex, Cursor, Gemini CLI, Copilot CLI and OpenCode read too.
shellcurl -fsSL https://briefkin.dev/skills/intercom-requests-weighted-by-revenue/install | shAsk Claude Code:
promptRun the intercom-requests-weighted-by-revenue skillOr paste the prompt instead of installing:
promptCollect feature requests from the last 90 days: Intercom conversations (tag "<feature request tag>" if set, plus untagged ones that ask for a feature), Zendesk tickets tagged feature_request, and threads in my Discord requests forum. Group them into features from my list: <feature: synonyms; ...>, and propose new names only for clusters of 3 or more. Count unique requesters per feature. Match each requester by lowercased email to a Stripe customer (MRR from active subscriptions, monthly, after discounts) and to HubSpot contacts with open deals; fall back to company email domain, never free-mail. Count a company's MRR and each deal once per feature; Discord requesters count but add no revenue. Rank features by MRR with the count rank beside it, flag features whose MRR rank is 3 or more places above their count rank, and give totals by source. End with the feature to prioritize first and the customers to tell when it ships.1st of the month at 9:00, from cron on any machine where Claude Code is signed in:
crontab0 9 1 * * claude -p "Run the intercom-requests-weighted-by-revenue skill"Add it with crontab -e. A laptop asleep at that time runs it when it wakes if you use launchd or Task Scheduler instead; GitHub Actions works for the API route.
Connect Briefkin once with curl -fsSL https://briefkin.dev/install | sh and every run lands on your board as a report card. How setup works
SKILL.md---
name: intercom-requests-weighted-by-revenue
description: "Monthly: 90 days of feature requests from support and Discord, ranked by the MRR of the customers asking and the open deals they hold up. Use when the user asks for this, or when it runs on a schedule."
---
# Feature requests weighted by revenue: support, Stripe and CRM
Monthly: 90 days of feature requests from support and Discord, ranked by the MRR of the customers asking and the open deals they hold up.
A feature request list sorted by count favors whoever writes in most: free users, small accounts, the regulars in Discord. The request that three of your biggest customers raised once each, and that two open deals mention, sits near the bottom of it.
Once a month the agent groups 90 days of requests from Intercom and Zendesk (and Discord, counted but not priced), matches each requester to their Stripe MRR and their open HubSpot deals, and ranks the requests both ways. Product managers see where count and revenue disagree; support and founders get a list they can answer customers from.
## Two ways to get the data
Use the API or MCP route when you have an MCP server, a CLI or an API token for the app. Otherwise, if you can drive a browser the user is signed in to (Claude in Chrome, a Playwright or Chrome DevTools MCP server), use the browser route. Say which one you used.
## Route A: API or MCP server
### What you need
- Read access to Intercom conversations or Zendesk tickets, and the feature-request tag if you use one; untagged requests are classified by the agent.
- The same customer email in Intercom or Zendesk, Stripe and HubSpot: each request is priced through its requester's email, or the company domain when that is all that matches.
- Read access to Stripe Customers and Subscriptions and to HubSpot contacts and deals; optionally a Discord bot with View Channels and Read Message History on the requests channel.
If something is missing, say what and stop; do not invent numbers.
### Steps
1. **Collect 90 days of requests** (Intercom): Intercom: `POST /conversations/search` with `created_at >` the Unix time 90 days ago, plus `tag_ids IN [<feature request tag>]` if you tag them, and `GET /conversations/{id}` for the messages and `source.author.email`. Zendesk: `GET /api/v2/search.json?query=type:ticket created>90days tags:feature_request` (your tag), then `GET /api/v2/users/show_many?ids=<requester_ids>` for emails.
2. **Add community requests** (Discord): For a feature-requests forum channel, list threads with `GET /channels/{channel.id}/threads/archived/public` and `GET /guilds/{guild.id}/threads/active`, keep those started in the 90 days (the thread ID is a snowflake that encodes the time) and read each starter message. Discord does not give bots members' emails, so these are counted but carry no revenue unless you keep a username-to-email list.
3. **Classify into features**: Map each request to one name on the feature list the person keeps, using its synonyms; read untagged conversations too, since many requests arrive inside a support question. Propose a new name only for a cluster of 3 or more unmatched requests. Count unique requesters per feature, not conversations, so a customer who wrote five times counts once.
4. **Look up each requester's revenue and deals** (Stripe): Stripe: `GET /v1/customers/search?query=email:"<email>"`, then the customer's active subscriptions for MRR (monthly, after discounts). HubSpot: `POST /crm/v3/objects/contacts/search` with `email IN [...]`, then `POST /crm/v4/associations/contacts/deals/batch/read` and the deals' `amount` and `hs_is_closed`, keeping open ones.
5. **Join and rank both ways**: Join on the lowercased requester email; when it misses, match the email domain to a Stripe customer or HubSpot company domain, never free-mail. A company with several requesters adds its MRR and each deal once per feature. Requesters with no Stripe customer count in the request total and add $0. Rank by MRR, show the count rank beside it, and call out any feature whose MRR rank is 3 or more places above its count rank.
## Route B: the browser
### What you need
- Signed in to Intercom or Zendesk as a teammate or agent, to the Stripe Dashboard (Analyst role or higher), to HubSpot with view access to contacts and deals, and to Discord as a member of the requests channel.
If something is missing, say what and stop; do not invent numbers.
### Steps
Start at https://app.intercom.com/. The user is signed in already; never type passwords or codes, and ask if a sign-in page appears.
1. **Collect requests in Intercom**: Open the inbox, search or filter by your feature-request tag and set the date to the last 90 days. For each conversation, note the requester's email and what they asked for. Read a sample of untagged conversations too, since requests often arrive inside support questions.
2. **Add Zendesk and Discord**: Zendesk: search `type:ticket created>90days tags:feature_request` and note requester and request. Discord: open the feature-requests forum channel, scroll through posts from the last 90 days and note each request and username.
3. **Group and count**: Map each request to a feature from the list, by name or synonym, and count unique requesters per feature. Propose a new feature only for 3 or more similar unmatched requests.
4. **Price the requesters**: In `https://dashboard.stripe.com/customers` search each email and read the active subscription amount per month. In HubSpot, open the contact (or company) and read the open deals in its **Deals** card. Count a company once per feature; Discord requesters add no revenue.
5. **Rank and report**: Rank features by MRR with the count rank beside it and the open deals, flag features 3 or more places higher by MRR than by count, give totals by source, and end with the feature to prioritize and the customers to tell when it ships.
Note: Looking up each requester by hand is slow past about 100 requests; the browser route then works best on the top features by count plus anything tagged by a paying account, and the API route covers the full set. Without a feature-request tag the browser route can only sample untagged conversations, so its counts run low.
## The report
- **Requests in 90 days**: how many, from how many people, by source.
- **Ranked by MRR**: each feature with unique requesters, count rank, MRR of paying requesters and open deals that mention it.
- **Where count and revenue disagree**: features that rank much higher by MRR than by count.
- **Proposed new features** from unmatched requests.
- What to do first: the feature with the most MRR and open pipeline behind it, and the customers to tell when it ships.
## Post it to Briefkin
When `BRIEFKIN_TOKEN` is set, or `~/.config/briefkin/env` exists (the installer from https://briefkin.dev/docs writes it), also send the result to the user's Briefkin board as one card. Keep the `item_key` the same on every run so the card updates in place, use a new `event_id` per run, and put today's real numbers in place of the example ones. If the request fails, say so once and carry on.
```bash
[ -n "${BRIEFKIN_TOKEN:-}" ] || . ~/.config/briefkin/env
curl -sS -X POST "${BRIEFKIN_URL:-https://briefkin.dev}/v1/events" \
-H "authorization: Bearer $BRIEFKIN_TOKEN" \
-H "content-type: application/json" \
-d @- <<'JSON'
{
"v": 1,
"event_id": "intercom-requests-weighted-by-revenue/<date of this run, e.g. 2026-10-16>",
"item_key": "intercom-requests-weighted-by-revenue",
"project": "Acme",
"source": "Feature requests weighted by revenue: support, Stripe and CRM skill",
"kind": "update",
"title": "SSO is 4th by requests but 1st by revenue",
"summary": "**SSO** came from 9 customers in 90 days, 4th by count, but they pay **$3,100 MRR**, more than any other request, and it holds up **2 open deals worth $40,000**. Dark mode leads by count with $620 MRR behind it.",
"widget": [
{
"type": "Table",
"props": {
"columns": [
"Request",
"Requesters",
"Count rank",
"MRR",
"Open deals"
],
"align": [
"left",
"right",
"right",
"right",
"left"
],
"rows": [
[
"SSO (SAML)",
9,
"4th",
"$3,100",
"2, $40,000"
],
[
"Bulk CSV import",
21,
"2nd",
"$1,850",
"None"
],
[
"Zapier integration",
17,
"3rd",
"$1,400",
"1, $8,000"
],
[
"Calendar sync",
8,
"5th",
"$900",
"None"
],
[
"Dark mode",
34,
"1st",
"$620",
"None"
]
]
}
},
{
"type": "Text",
"props": {
"text": "214 requests from 146 people: Intercom 128, Zendesk 61, Discord 25 (counted, not priced).",
"variant": "muted"
}
},
{
"type": "Callout",
"props": {
"text": "Woodgrove Bank ($28,000) and Relecloud ($12,000) list SSO as a blocker. When ENG-412 has a date, tell them and the 9 paying requesters.",
"tone": "info"
}
}
]
}
JSON
```
Widgets come from the Briefkin catalog (https://briefkin.dev/v1/catalog). Without a token, just give the user the report.
## Run it on a schedule
Suggested: 1st of the month at 9:00 (`0 9 1 * *`). From cron, with the agent signed in on that machine:
```bash
0 9 1 * * claude -p "Run the intercom-requests-weighted-by-revenue skill"
# Codex: codex exec, Gemini CLI: gemini -p, Copilot CLI: copilot -p, OpenCode: opencode run
```
Or use the agent's own scheduler (Claude Code routines, Codex automations, Claude or ChatGPT scheduled tasks): https://briefkin.dev/skills/intercom-requests-weighted-by-revenue#schedule
Source: https://briefkin.dev/skills/intercom-requests-weighted-by-revenue
Read access to Intercom conversations or Zendesk tickets, and the feature-request tag if you use one; untagged requests are classified by the agent.
The same customer email in Intercom or Zendesk, Stripe and HubSpot: each request is priced through its requester's email, or the company domain when that is all that matches.
Read access to Stripe Customers and Subscriptions and to HubSpot contacts and deals; optionally a Discord bot with View Channels and Read Message History on the requests channel.
https://mcp.intercom.com/mcp (https://mcp.eu.intercom.com/mcp for EU workspaces; Australian workspaces aren't supported yet). Intercom is in Claude's connector directory for US workspaces, and on Team and Enterprise plans an Owner adds it. Its tools search and fetch conversations and contacts (docs).INTERCOM_ACCESS_TOKEN, and call https://api.intercom.io (api.eu.intercom.io or api.au.intercom.io by region) with an Intercom-Version header. Give the app Read conversations and Read and list users and companies.The MCP server includes a few write tools (internal notes, Help Center articles), so for unattended reports an app token with read permissions only is the tighter option.
ZENDESK_SUBDOMAIN, ZENDESK_EMAIL and ZENDESK_API_TOKEN and sends basic auth as {email}/token:{token}.read scope.An API token acts as the user who made it, with that agent's full rights; an OAuth token with only read can't update, assign or close tickets.
DISCORD_BOT_TOKEN and send it as Authorization: Bot <token>; the skill also reads DISCORD_CHANNEL_IDS, the channels to watch.Keep the bot out of every channel the report doesn't cover with channel permission overrides, and leave out Send Messages unless you want it to post the digest back into Discord.
https://mcp.stripe.com. Add Stripe from Claude's connector directory, or run claude mcp add --transport http stripe https://mcp.stripe.com/, and sign in with OAuth; clients without OAuth can send a restricted key as a Bearer token.stripe login once, then stripe subscriptions list --status active --limit 100 or stripe invoices list --status open. The CLI defaults to test mode, so add --live for real data.rk_live_...) in the Dashboard under Developers > API keys, store it in STRIPE_API_KEY, and give it Read on the resources the report touches: Subscriptions, Invoices, Charges, Customers, PaymentIntents, Balance and Disputes.Never hand an agent the secret key (sk_live_...); a restricted key with Read where needed and None everywhere else can't refund, cancel or charge anything.
https://mcp.hubspot.com. HubSpot also offers a Claude connector built on the same server; you sign in with your HubSpot user and it sees what that user can see (docs).crm.objects.deals.read, crm.objects.contacts.read, crm.objects.companies.read, crm.objects.owners.read), and store its token in HUBSPOT_ACCESS_TOKEN.The MCP server and connector can create and update records, so for unattended reports a private app with only .read scopes is the safer credential.
They count toward the number of requesters and add $0 MRR. They are usually free or trial users, or a colleague of a paying customer writing from another address; the domain fallback catches the second case for company domains. If a feature's requesters are mostly unmatched, the card says so rather than ranking it low.
Ninety days collects enough requests to rank and stays recent enough that the requester still cares. Each month's run covers a fresh 90-day window, so a request drops off three months after it was made. MRR is read on the day of the run, so a customer who has since churned adds nothing.
No. The skill runs with your own agent and gives you the report in the chat. With a Briefkin token set, each run also posts it to your board as a report card, so you can glance at it instead of asking again.
Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot CLI, OpenCode, Windsurf and Amp all read SKILL.md files. The install command puts it in ~/.claude/skills and ~/.agents/skills, where they look. ChatGPT, the Claude app and Grok take the prompt instead. Pick your agent under "Install and run it" and the commands change to match.
Yes. Switch the data source to "Your browser" and the steps change to the Intercom, Zendesk, Discord, Stripe and HubSpot pages themselves: the agent opens app.intercom.com in a browser you are signed in to and reads the numbers off the page. Claude Code, Codex, Cursor, Claude app and ChatGPT can drive a browser out of the box; Gemini CLI, Copilot CLI and OpenCode need a Playwright or Chrome DevTools MCP server first. It is slower than the API and needs you signed in, so it suits a report you run by hand or from a scheduler on your own computer.
Skills are free to use with any agent. Briefkin is where their results land: one board for every report, number and question your agents send, with a ping when something needs you.
Free during the open beta. No card.