---
id: casos/funil-por-canal
area: RevOps
usage: widely used
effort: medium
grain: Deal with a single channel; rolled up to channel x entry month x stage
---

# Funnel by channel

Each source channel's conversion at every funnel stage, with a single channel per deal and without hiding the deals that arrived with no source.

## Executive summary

**For:** Marketing, sales and RevOps teams that decide where to put effort and budget by channel.

**What it solves**

- Each deal has one channel, set by a rule every dashboard repeats.
- The comparison shows where each channel loses: at the top, in the middle or at closing.
- Deals with no source show up as such, instead of vanishing or inflating a channel.

**Why it matters:** The average conversion hides channels that bring volume and do not close, and small channels that close almost everything. Without one channel per deal, the same lead counts in two channels or in none, and budget decisions become opinion. It is the bridge between media, CRM and revenue.

**Business questions it answers**

- Which channel brings the most sales for each lead that comes in?
- At which stage do paid media leads get stuck, compared with referrals?
- How many leads arrived with no identified source last month?
- Did the organic qualification rate drop in August?
- How long does each channel take from lead to sale?

**What you need**

- CRM connected with stage history and the source fields (UTM, source, channel)
- The marketing automation tool or forms that store the conversion UTM
- The official channel list and the priority order between signals

**What you get**

- A table with one channel per deal and the rule that classified it
- Funnel by channel and entry month, with stage to stage conversion
- Dashboard comparing channels side by side, with volume next to the rate
- An AI agent that answers by channel with the rule already applied

## Detailed

### The problem

The lead source is scattered: UTM on the form, an encoded traffic_source in the marketing automation tool, a free text field in the CRM, gclid and fbclid in the URL. Each dashboard picks one field, the same deal counts in different channels and a large share ends up with no channel or in a generic one. The channel comparison becomes unfair and budget follows whoever speaks loudest.

### Business rules

1. **One channel per deal, by cascade.** Define an order of signals and keep the first one that exists: click id or paid UTM (gclid, gbraid, wbraid, fbclid, li_fat_id, utm_source with a paid medium), then internal identifiers (product signup, event, partner), then the session referrer (search engine becomes organic, social network becomes organic social, AI assistant becomes AI), then the CRM source field and, last, No source. Store in another column which rule classified each deal. (Avoid: Use whatever source field is filled in on the day's dashboard.)
2. **The channel is the entry channel and does not change.** Use the deal's entry source (first conversion or creation), not the last interaction. A deal that comes back through another channel stays in its entry channel; a last touch reading, if useful, goes in another column. Some CRMs keep only the card's current source: rebuild the entry from the contact's first conversion. (Avoid: Read the contact's latest source, which changes with every visit.)
3. **Decode the source before giving up on it.** RD Station stores the source in traffic_source with the encoded_ prefix and a base64 JSON of the first and last session; traffic_medium and traffic_campaign are almost always empty. What looks like missing tracking is encoding. On Meta's native form (Lead Ads), the lead never visits the site and arrives without UTM: link it by form or ad id, or by the first visit URL ids tested against the real campaign ids. (Avoid: Mark everything without utm_source as no source.)
4. **How the record was created is not a channel.** In HubSpot, hs_analytics_source = OFFLINE means the record was created by import, integration or by hand, not that the lead came from an offline channel. Before accepting OFFLINE, look for UTMs in the fields of the deal and of the associated contact. (Avoid: Count OFFLINE as a channel.)
5. **Paid, organic and outbound never mix.** Always separate paid leads from organic ones, and active prospecting (outbound, cold calls, WhatsApp blasts, SDR) from inbound. Volume that comes in through batch loads, list imports or system integrations is not a lead: in a real case, 3 in 4 conversion events were imports. (Avoid: Count every contact created as a lead of the channel.)
6. **Normalize names before grouping.** Keep a reference table with every spelling of each channel, lowercase and without accents (in a real case, 60 spelling variants for a handful of sources). Separate channel, the messenger (ad, WhatsApp, referral), from origin, the subject (the event, the campaign, the content). (Avoid: Group by the field's raw text.)
7. **Compare channels in the same cohort and with the same yardstick.** Channel conversion is measured within the deal's entry month and with the same stage definition for every channel. Recent cohorts have not had time to close yet: flag the window as incomplete until the average cycle of the slowest channel has passed. (Avoid: Compare the month's sales with the month's leads, by channel.)
8. **No source is a funnel row.** Show No source as a channel, with its own volume and conversion. Never allocate it across the other channels. If the client decides that 'unknown' counts as digital, record the decision; '(no source)' stays out. (Avoid: Hide or spread the deals with no channel.)
9. **A small channel is not a conclusion.** Channels with few deals in the cohort produce rates that swing a lot from one month to the next. Show volume next to the rate and only compare channels above a declared minimum number of deals. (Avoid: Conclude that a channel with 4 deals converts at 50%.)

### Channel cascade

Top to bottom: the first matching rule sets the deal's channel.

- **gclid, gbraid, wbraid or utm_source google with a paid medium** → Google Ads
- **fbclid or utm_source fb, ig, meta with a paid medium; Lead Ads form id** → Meta Ads
- **li_fat_id or utm_source linkedin with a paid medium** → LinkedIn Ads
- **WhatsApp conversation with the ad click id** → Click to WhatsApp (`ctwa_clid`)
- **referral, partner or event field** → Referral, partner or event
- **cadence, cold call, blast or SDR** → Outbound
- **search engine referrer, no UTM** → Organic search
- **social network referrer, no UTM** → Organic social
- **AI assistant referrer** → AI
- **no signal found** → No source

### Definitions

| Metric | Definition |
|---|---|
| Deal channel | first cascade signal found at the deal's entry; one per deal, frozen |
| Channel lead | deal created in the acquisition funnel in the month, with that channel, excluding imports, tests and duplicates |
| Channel MQL and SQL | entry into the qualification stage and the opportunity stage, by the same yardstick for every channel |
| Channel conversion by stage | channel deals that reached the next stage / channel deals that entered the stage, in the entry month cohort |
| Channel sales rate | sales / channel leads in the same cohort, only with a mature window |
| Channel cycle | median days between entry and win, for the channel's won deals only |
| No source share | No source deals / all deals in the month |

### Pitfalls

- **A source that looked empty.** The marketing automation medium and campaign fields were empty in almost every event, and the team assumed there was no tracking. The source was in base64 inside traffic_source. How to avoid: Decode traffic_source before concluding UTMs are missing.
- **An integration became a channel.** A system integration generated 9 in 10 conversion events of the period and inflated an entire channel. How to avoid: Exclude batch loads and integrations by the event source.
- **Lead Ads with no channel.** Leads from Meta's native forms reached the CRM with less than 1% UTM fill and fell into No source. How to avoid: Link by form id or by the ad ids in the first visit URL.
- **One field, five formats.** The same source field held base64, query strings, free text, app URLs and blanks. How to avoid: Handle each format in one step of the cascade, with a test per format.
- **Platforms added up exceed the CRM.** Adding the conversions reported by Google and Meta gave more leads than the CRM, because each platform credits the conversion on the click date and neither deducts the other. How to avoid: Count leads and sales by channel only in the CRM; platforms bring spend and clicks.
- **Manual channel without audit.** The channel picked by hand on the card did not match the tracked source and nobody noticed. How to avoid: Cross the manual channel with the expected source in a reference table and show the mismatches.

Validated on real data: In Nekt's own HubSpot account, more than half of the deals have hs_analytics_source = OFFLINE because they were created by integration or import. Almost 3 in 10 of those deals have a UTM filled in a field of their own: accepting OFFLINE as a channel would pull these leads out of the channel they came from.

### Acceptance test

- [ ] Every funnel deal has exactly one channel and one recorded classification rule.
- [ ] The sum of leads across all channels, including No source, equals the month's total leads in the funnel.
- [ ] Leads and sales by channel for a closed month match the CRM or marketing automation source report (difference under 2%).
- [ ] No import, test or integration deal appears as a channel lead.
- [ ] Running again does not change the channel of any deal already classified.

### Context document

```text
Funnel by channel
- Source: funnel by channel table. Deal channel = the channel column, one per deal, set at entry and frozen.
- Cascade: paid click or UTM > internal identifier (product, event, partner) > session referrer > CRM source > No source.
- hs_analytics_source = OFFLINE is how the record was created, not a channel.
- Leads, MQLs, SQLs and sales by channel come only from the CRM. Media platforms bring only spend and clicks.
- Paid, organic and outbound are separate. Imports, tests and integrations are not leads.
- Channel conversion is measured in the entry month cohort. A cohort younger than the average cycle is flagged as incomplete.
- No source is a visible channel. Never allocate it.
- Always show volume next to the rate. Do not compare channels with fewer than <minimum> deals in the cohort.
Client exceptions:
- <client>: 'unknown' counts as digital; '(no source)' stays out.
- <client>: channel list and spellings in <reference table>.
```

### Variations

- **Cost per stage:** Join spend by channel and month to get CPL, cost per MQL, cost per SQL and CAC.
- **By campaign:** Go from channel down to campaign with the normalized utm_campaign matched against the campaign name or id on the platform.
- **Multi-client:** For agencies, the same cascade per client, with exceptions in a configuration table.
