# See which Keap lead sources actually produce revenue

> Pick a date range and rank every lead source and tag cohort by contacts, opportunities, closed revenue and how long those buyers take to buy.

- Workflow type: app
- Services: Keap, Google Sheets
- Categories: Marketing, Sales
- Published: 2026-08-31

## What it does

- One table that ranks every lead source and tag cohort by contacts acquired, opportunities created, closed revenue, average order value, and the typical number of days from first contact to first purchase
- Click any row to see the individual contacts behind the number and the products they actually bought
- A second view built from your opportunity stage history showing stage to stage conversion and average time in each stage, so you can tell a source that produces buyers from one that produces stallers
- Act on a cohort without leaving the page: tag a segment for follow up, push an underworked source into a nurture sequence, or send the table to Google Sheets for the monthly board pack
- A Write the channel review button that has an assistant compare this period against the previous one and write a plain English narrative with budget recommendations, saved so past reviews stay browsable

## What you'll need

- A Keap account where contacts carry a lead source or source tags
- Orders and opportunities recorded in Keap, so revenue can be traced back to where the person came from
- A Google account and a spreadsheet, only if you want the export for board packs
- A published Keap campaign sequence, only if you want to enroll a cohort into nurture from the page

## Prompt

Build me an app that answers the one question Keap will not: which lead sources and campaigns actually produce revenue. I open it, pick a date range, and get a cohort report I can explore and act on.

Before the report runs I choose how a cohort is defined. Option one is the lead source field on the contact record. Option two is a tag category, because plenty of Keap accounts encode source in tags rather than the lead source field: load the categories with List Tag Categories and let me pick one, and every tag inside that category becomes a cohort row. Keep this choice sticky between visits, along with my last date range and minimum cohort size.

The main view is a single table with one row per cohort. Columns: contacts acquired in the range, opportunities created, closed revenue, average order value, revenue per contact acquired, and median days from first touch to first purchase. Contacts come from List Contacts filtered to the date range, opportunities from List Opportunities, revenue from List orders, and the order total is matched back to the buying contact so revenue lands on the cohort that acquired them. Sort by closed revenue by default and let me sort by any column.

Attribution rule that matters: attribute an order to the buyer's cohort at the time of acquisition, not their current state. If someone was retagged or their lead source was edited last month, last quarter's numbers must not silently change. Snapshot the cohort assignment from the contact's acquisition date when the report is built, and store it with the computed report so a re-open shows the same figures.

Bake in a minimum cohort size, defaulting to ten contacts and adjustable in the UI. Cohorts under the threshold are not ranked in the main table. Show them in a separate collapsed section labelled as not enough data, with their raw counts visible, so a source with three contacts and one lucky order cannot top the chart. Use the median for days to first purchase, never the mean, because a single ancient contact who finally bought will wreck an average.

Clicking any row drills into that cohort: the individual contacts, when each was acquired, whether they ever opened an opportunity, what they have spent, and their product mix resolved through List Products so I see product names rather than ids. Where a contact's tags matter for the drilldown, read them with List Applied Tags (Contact). Let me sort this list by spend and filter it to buyers only.

A second view is the stage funnel. Use List of Opportunity Stages for the stage order and List Opportunity Stage Moves for the historical stage-move records, which is what makes real conversion and dwell time possible instead of a snapshot of where deals sit today. For each cohort show stage to stage conversion and average days in each stage, so I can tell whether a channel produces leads that buy or leads that stall. Highlight the stage where each source loses the most deals.

From any cohort I can act without leaving the page. Apply Tag marks the whole segment for follow up, with a confirmation showing how many contacts will be tagged. Add Contacts to Campaign Sequence pushes an underworked source's leads into a nurture sequence, with the campaign chosen from List Campaigns and the sequence from Retrieve a list of Sequences for a Campaign. An Export button writes the current cohort table to Google Sheets using Append Values, with a timestamp and the date range on every row so the monthly board pack accumulates rather than overwrites. Both write actions run against the contacts currently in view and report per contact success or failure back on screen.

Add a Write the channel review button that kicks off a background agent. The agent pulls the same cohort figures for the selected period and for the immediately preceding period of equal length, compares them, and writes a plain English narrative: which sources grew or shrank, which produce buyers versus stallers based on the stage data, which look expensive relative to the revenue they return, and a short set of budget recommendations naming specific sources to increase, hold or cut. It must respect the minimum cohort size and say plainly when a movement is too small to be meaningful. Store each finished review in the app with its date range and generation time, and give me a Reviews view listing past reviews newest first so the whole history stays browsable and I can reread what we decided last quarter.

Keap API notes to build against: monetary amounts are decimals in whole units, not minor units, so do not divide by one hundred. The v2 list endpoints use cursor pagination with page_size plus page_token, and every list here needs to page fully before totals are computed, because a partial page silently understates a cohort. Custom fields come back in a custom_fields array keyed by numeric id, so resolve ids to names once rather than hardcoding them. Fetching a full range is slow, so show progress while the report builds and cache the computed report per date range and cohort definition instead of refetching everything on each view switch.

## How to customize

- Choose whether a cohort is defined by the lead source field on the contact or by one of your tag categories, since plenty of teams encode source in tags instead
- Set the minimum cohort size so a source with three contacts cannot top the chart on the back of one lucky order
- Change which period the written review compares against, and which spreadsheet and tab the export appends to

## FAQ

### Does this change anything in my Keap account?

Not unless you ask it to. Building the report only reads your contacts, opportunities, orders and products. The only things that write back to Keap are the buttons you press yourself: applying a tag to a cohort, or adding a cohort to a campaign sequence.

### We track lead source in tags, not the lead source field. Does it still work?

Yes. You choose how a cohort is defined before the report runs. Pick the lead source field on the contact record, or pick one of your tag categories and every tag in it becomes a row in the table.

### Will a source with only a handful of contacts skew the ranking?

No. There is a minimum cohort size you control. Sources below it are shown separately and marked as not enough data rather than ranked, so a single lucky order cannot put a three contact source at the top.

### How does it decide which source gets credit for an order?

Credit goes to the cohort the buyer belonged to when they were acquired, not whatever source or tag they carry today. That way retagging people later does not quietly rewrite last quarter's numbers.

### Do I need Google Sheets to use this?

No. Sheets is only used for the export button, which appends the cohort table to a spreadsheet for reporting. Skip it and the rest of the app works exactly the same.

### Can I see why a channel underperformed, not just that it did?

Yes. The stage view uses your opportunity stage history to show where each source's deals actually stall and how long they sit in each stage, and the written review turns that into plain English with a budget recommendation.

Use this prompt in General Input: https://www.generalinput.com/prompts/see-which-keap-lead-sources-actually-produce-revenue