RD events, CRM Source field and GA4
Decoding and per-client cascade
One channel per lead and cost per lead by channel
Report, alert and AI agent
What it solves
- Each lead has exactly one channel, with the rule that classified it next to it.
- Leads with no source become a visible row and an alert, not a generic channel that hides the problem.
- Cost per lead by channel divides spend by paid leads, not by the CRM total.
Business questions it answers
Ask your agent these questions once the case is live.
What you need
- RD Station Marketing and each client's CRM connected to Nekt
- The channel list and cascade order agreed with each client
- Each client's decisions on ambiguous sources, such as Desconhecido (Unknown)
What you get
- A lead table with channel, platform, applied rule and source format
- Cost per lead by channel and by platform using paid leads only
- An alert when the no-source share exceeds the client's limit
- An AI agent that explains the difference between platform, RD and CRM
Where to activate
Leads and cost per lead by channel, with the no-source share always visible.
Warns when the no-source share jumps from one week to the next, naming the form that changed.
Explains why Meta says 40 and the CRM says 27, without picking one number.
Decoding is the same for everyone. The work is writing each client's cascade and exceptions and keeping them as data. The detailed view has the business rules, the pitfalls and the acceptance test. Or send everything straight to your agent with the Nekt MCP.
The lead source arrives in five formats in the same field: base64, query string, free text, app URL and empty. Integrations between the CRM and marketing automation write an event at every stage change, and base imports show up as conversions. Each client decides differently what to do with the Desconhecido (Unknown) source, and the platform, RD and GA4 count the same lead in different ways.
How it is usually done, and the rule
Each row is a mistake that already happened in practice.
In RD Station, traffic_source may arrive as encoded_<base64>, holding a JSON of the first and last session; traffic_medium and traffic_campaign are almost always empty. Inside the JSON the source still shows up as UTMs, as the legacy __utmz cookie or as a raw URL. Classify each row by format and separate empty from unrecognized format: no source and a source we could not read are different states.
Exclude base import, CRM sync, integration, manual insert, mailing, blast, list and test events by event identifier. In real accounts, three quarters of conversion events were bulk loads, and a CRM to RD integration produced 9 out of 10 events. Use word boundaries: without them, a form called Fale com um Especialista (talk to a specialist) falls into the list filter. Flag the event as excluded instead of deleting it, so the difference can be explained.
Each client has its own signal order: manual override, click identifier (gclid, gbraid, wbraid, fbclid, li_fat_id), paid UTM, UTM stored on the contact, session source, CRM Source field and, last, no source. Store the order and the terms of each channel in a per-client table, never copied from another client. Order changes the count: a short term like fb matches anywhere in the text.
Each lead carries channel, platform, the rule that matched and the source format. When the client challenges a number, the answer shows why that lead is Meta and not organic, and a rule change becomes visible in the series.
For one client, the Desconhecido (Unknown) source counts as digital, because almost all of those deals had a site conversion in the previous 30 days; (sem fonte) (no source) stays out, because it is sales creating deals by hand. For another client, Unknown does not count as paid. Record the decision, the date and the test that backed it. Test with a conversion in the 30 days before deal creation, not with the contact existing in the base, which absorbs almost everyone.
Unidentified never disguises itself as direct and is never prorated across channels. Show volume and share per month and alert when it passes the client's limit (15% and 25% were real limits). A jump from one week to the next is almost always broken tracking: a custom form that does not send source fields, a redirect that drops the query string or a chatbot with no UTM.
Lead Ads do not go through the site and arrive with no UTM. In RD, Meta native form conversions have an identifier ending in a hyphen and 9 or more digits, and forms with LINKEDIN in the name come from the LinkedIn native form. Classify by the signature before falling into no source.
Lead, opportunity and sale by channel come from RD or the CRM, which tie the source to the person. Spend, clicks and platform conversions come from the platform, which credits on the click date and does not discount the other platform. Sessions and behavior come from GA4, which does not know the lead. GA4 channel and CRM channel are not summed or crossed.
Cost per lead = period spend / paid media leads created in the period. Cost per lead by platform = platform spend / that platform's leads. Organic, direct, chatbot with no source and Unknown stay out of the denominator. With no paid lead, cost per lead is null, not zero. Spend / all leads can appear alongside, labeled as a floor.
Leads confirmed by the team that have no UTM get their channel through a manual override, stored in a table with who, when and why, and applied at the top of the cascade. Never fix the channel directly in the output or in the report spreadsheet.
Typical channel cascade
The first rule that matches wins. The order and the terms belong to each client.
Definitions
spend / paid media leads in the period; null with no paid leadspend in the period / leads whose channel is that platformspend / all leads; shown only labeled as a floorPitfalls that already happened
Medium and campaign fields were empty in almost every event and the team concluded there was no tracking. The source was in base64 inside traffic_source.
Decode before classifying.
An integration between the CRM and marketing automation wrote an event at every stage change and multiplied conversions by ten.
Exclude by event identifier and show exclusions separately.
A list filter without word boundaries removed the Meta native form that generated the most leads.
Word boundaries on every short term.
The share of conversions with no source jumped from under 10% to about half from one week to the next, after a change to the site form.
Track the share weekly and treat it as instrumentation, not analysis.
The WhatsApp chatbot arrived with the vendor's name as source and no medium, and accounted for about a fifth of the month's leads.
Label it WhatsApp with no source and ask the vendor to pass the UTM. Do not redistribute by estimate.
Matching client labels between Google Ads and RD by name got few pairs right and merged different brands.
Use the campaign ID and the account to client registry.
Acceptance test
The case is done when every item passes.
- Every lead has exactly one channel and one applied rule, and the sum of leads by channel equals total leads.
- No import, integration, mailing or test event enters the count, and exclusions appear separately with their identifier.
- For one client and month, the sum of paid leads by platform equals paid media leads, and cost per lead equals spend / paid leads.
- Rows with an unrecognized source format stay below 1% of the rows that have a source.
- No source appears as its own row, and the alert fires when the share passes the client's limit.
Agent package
Paste into Claude, ChatGPT or any client with the Nekt MCP connected.
Lead source and channel - Leads and lead channel come from RD Station or the CRM. The ad platform is for spend, clicks and platform conversions. GA4 is for sessions. Do not add or cross the three. - traffic_source with the encoded_ prefix is base64 holding a session JSON: decode before classifying. Empty and unrecognized format are different states. - Exclude import, CRM sync, integration, manual insert, mailing, blast, list (with word boundaries) and test events. - Channel = first rule that matches in the client's cascade: manual override, click ID, paid UTM, contact UTM, session source, CRM Source field, no source. - Identifier ending in -<9 or more digits> = Meta native form (paid). - No source never becomes direct and is never prorated. If the share passes the client's limit, warn and say since when. - Cost per lead = spend / paid media leads. With no paid lead, cost per lead is null. - The platform credits the conversion on the click date and does not discount the others. When platform and CRM disagree, explain both counts instead of choosing one. - A sale conversion showing on the platform may have been sent by the agency: it is not independent measurement. Per-client exceptions: - <client>: source Desconhecido (Unknown) counts as digital but not as paid; (sem fonte) (no source) stays out. Decision from <date>. - <client>: no-source alert above <x>% of the month's leads. - <client>: chatbot <name> with no UTM becomes WhatsApp with no source and does not count as paid media.
Build the "Lead source and channel" case in my Nekt workspace following the rules at https://academy.nekt.com/en/industrias/agencias/origem-canal-do-lead.md. 1) Find the source tables and confirm the columns the rules use. 2) Create a transformation at the stated grain applying every rule. 3) Run the acceptance test and show me the result of each item. 4) Create the case's context document in the workspace, leaving my clients' exceptions open for me to fill in.
Variations
Carry the lead channel through MQL, SQL and sale in each client's CRM.
Store the source of the first and last conversion in separate columns and state which one the report uses.
The same logic over GA4 sessionSource and sessionMedium, without crossing it with the lead channel.