AON built one of the most rigorous marketing KPI charters we have seen at a $14B company.
Every formula documented. Every persona mapped. The data exists in Databricks.
Three business rules were never encoded in the platform. They block every commercial KPI
the CMO needs for the board. Context Engineering writes them once — and every tool reads them forever.
Each persona has a well-defined accountability, real data in the MDL, and a specific KPI that is currently unanswerable. They do not share tools. They should share definitions.
Reports to the CRO. Every quarter the same question: did marketing generate pipeline, or did Sales generate pipeline that marketing touched?
The MDL returns a different answer depending on which lead_source field you query.
Sarah uses Power BI Copilot on her laptop.
Allocates budget across LinkedIn, content syndication, webinars, and in-person events. Cost per MQL by channel is her single most important signal — but MQL means different things in Eloqua vs Aon Connect vs the MDL. Every campaign comparison is fiction. She uses Genie in Databricks.
Runs EMEA's event programme: forums, roundtables, executive dinners. Cvent registration data exists in Eloqua as a Custom Data Object. Pipeline data exists in Aon Connect. Nobody has documented the five-hop join between them. Marcus cannot run an event ROI report. He uses Claude.
Ten of the highest-priority KPIs from AON's working document. Every formula is agreed. Every source system is identified. Stage 2 means the data exists — the definition has never been encoded.
| KPI Name | Persona | Stage | Blocker | Business Value | CE Outcome |
|---|
These are not data quality problems. The data exists, the sources are mapped, and the joins are documented. Three agreed business rules were never encoded anywhere in the platform.
AON's marketing attribution question has two answers because the MDL has two lead_source fields — and no agreed rule for which one to use.
Marketing uses C_Lead_Source___Original1 from Eloqua, which captures the original first-touch channel at the moment the lead was created.
Sales uses lead_source from Aon Connect, which reflects the current field value — updated whenever a rep takes ownership of a lead.
Neither field is wrong. They measure different things: Eloqua records what marketing did first; Aon Connect records what the business decided later. Without an agreed rule encoded in the platform, every dashboard author picks their own field, and every report produces a different number.
This single unresolved rule blocks six KPIs: Marketing-Sourced Pipeline, Marketing-Attributed Pipeline, Marketing Pipeline as % of Total, Marketing ROI, Closed-Won Revenue (Marketing-attributed), and Pipeline Influenced per Campaign. Sarah cannot present a defensible pipeline number to the board until this is encoded.
lead_source encodes the agreed allowlist permanently in Unity Catalog. All downstream tools — Power BI, Genie, SQL — read the same rule. Zero replication. One source of truth.
A Marketing Qualified Lead is the most important quantity in marketing operations — it governs budget allocation, sales handoff, and conversion rate reporting.
AON does not have a stable MQL definition. The MDL has no is_mql flag. To count MQLs, every tool must derive the value from two fields: lead_status_code = 'QUALIFIED' AND lead_stage = 'MQL' — but nobody documented that rule, so every report implements it differently.
The EA comment raises an additional complication: "Sales Accepted" is also a valid SQL stage — not just Converted. So MQL-to-SQL conversion rate is computed with different denominators and numerators depending on who runs it. The metric that governs Priya's entire channel allocation is fiction.
Priya needs to make a Q4 budget reallocation decision in three weeks. Without a stable MQL count, Cost per MQL by channel is guesswork. She cannot tell whether Events at £3,240 per MQL is genuinely cheaper than Paid Social at £8,100 — because the MQL counts driving those numbers use different derivation logic.
lead_status_code and lead_stage encodes the two-field derivation rule. The mv_marketing_pipeline Metric View bakes it into a governed mql_volume measure. Priya gets stable numbers. Genie, Power BI, and SQL all use the same rule.
London Insurance Forum ran on 15 July 2026. 340 attendees. £180,000 budget. Marcus knows the event generated significant pipeline — he can name three deals that started with conversations in that room. His CFO has asked for the pipeline number before approving next year's events budget. The data exists in Databricks. The join chain has never been written down.
Cvent registration data enters the MDL via an Eloqua Custom Data Object called SYS_Cvent_Event. Reaching pipeline from there requires five hops: through the campaign master, the campaign membership bridge, the lead table, and finally the opportunity table. No attribution window has been agreed — different team members use 30, 60, or 90 days depending on who you ask.
The answer is not missing because the data is missing. It is missing because the five-hop join and the attribution window have never been formalised and encoded. Every analyst who attempts this query builds the join from scratch, uses a different window, and gets a different number.
mv_event_attribution Metric View encodes the complete five-hop join chain and the agreed 90-day attribution window as a single governed measure: post_event_pipeline_90d. Marcus asks the question. Every tool returns $12.5M. Event ROI: 6.9×.
Context Engineering does not add a layer. It encodes agreed business rules as permanent objects in Databricks Unity Catalog — exactly where every downstream tool already looks before answering any question.
ALTER TABLE lead_attributes_it
ALTER COLUMN lead_source
COMMENT 'Agreed allowlist: Event,
Content Syndication, Paid Social,
Webinar, Email Campaign …'
measures:
- name: mql_volume
expr: COUNT(DISTINCT CASE
WHEN lead_status_code='QUALIFIED'
AND lead_stage='MQL'
THEN lead_id END)
measures:
- name: post_event_pipeline_90d
expr: SUM(CASE
WHEN opty_created_date BETWEEN
event_start_date AND
DATE_ADD(event_start_date,90)
THEN opty_amount_usd END)
Once encoded in Unity Catalog, the business rule belongs to the platform — not to any one tool. Sarah, Priya, and Marcus each use a different interface. They all get the same governed answer.
measure: marketing_sourced_pipeline
field: C_Lead_Source___Original1
allowlist: Event · Content Syndication
Paid Social · Webinar · Email Campaign
source: aon_mdl_test.marketing.lead_attributes_it
measure: mql_volume
instruction: "MQL derivation: lead_status_code
= QUALIFIED AND lead_stage = MQL.
Do not attempt to derive manually."
source: aon_mdl_test.marketing.mv_marketing_pipeline
/ai-gateway/mcp-services/system.ai.genie_one_mcp. Genie reads the Metric View, which encodes the five-hop Cvent join chain and the 90-day window. Marcus gets a defensible number without building a single JOIN.
measure: post_event_pipeline_90d
window: 90 days from event_start_date
join_chain: SYS_Cvent_Event → campaigns
→ members → leads → opps
source: aon_mdl_test.marketing.mv_event_attribution
The CE layer sits between the MDL's Gold zone and all consumer tools. Unity Catalog is the single source of semantic truth — column comments, Metric Views, and the Genie Knowledge Store are the three artifacts. No new infrastructure. No new data movement.
End-to-end journey of a lead — from first marketing touch through five source systems into the MDL Gold zone. Two fields capture the same lead with different values; the conflict between them is the attribution war.
╔══════════════════════════════════════════════════════════════════════════════════╗ ║ PERSON / PROSPECT (a marketing contact at a target account) ║ ╚══════════════════════════════════════════════════════════════════════════════════╝ │ │ │ │ fills a form registers for attends visits website / downloads content London Forum webinar clicks email │ │ │ │ ▼ ▼ ▼ ▼ ┌─────────────┐ ┌──────────────┐ ┌──────────────┐ ┌─────────────────┐ │ ELOQUA │ │ CVENT │ │ ON24 │ │ ELOQUA │ │ │ │ (event reg) │ │ (webinar) │ │ (web tracking) │ │ Creates lead│ └──────┬───────┘ └──────┬───────┘ └────────┬────────┘ │ │ │ pushes via API │ pushes via API │ │ C_Lead_ │ │ │ │ │ Source___ │ ▼ ▼ │ │ Original1 │ ┌──────────────────────────────────────────────┐ │ │ ← FROZEN │ │ ELOQUA CDO · SYS_Cvent_Event │◀──┘ │ at birth │ │ Custom Data Object — event registrations │ └──────┬──────┘ └──────────────────────┬───────────────────────┘ │ │ │ ┌────────────────────────────────────────────┐ │ │ RELTIO MDM · Master Data Management │ │ │ Resolves: duplicate contacts, company │ │ │ hierarchies, account golden records │ │ └───────────────────┬────────────────────────┘ │ │ │ ┌───────────────────▼────────────────────────┐ │ │ UNITY CDP · Customer Data Platform │ │ │ "Is this Eloqua contact the same person │ │ │ as this Aon Connect contact?" │ │ │ Cross-system identity resolution │ │ └───────────────────┬────────────────────────┘ │ │ ▼ │ ┌──────────────────┐ │ │ AON CONNECT │◀───────────────┘ │ Oracle Sales │ Eloqua syncs lead → Sales reps take ownership │ Cloud (CRM) │ │ │ │ lead_source │ ← MUTABLE — rep can change this field any time │ │ │ Creates: │ │ Opportunities │ │ Pipeline values │ └────────┬─────────┘ │ ╔═══════════════════════════════════════════════════════╗ ║ THE CONFLICT ZONE ║ ║ ║ ║ Eloqua field: C_Lead_Source___Original1 ║ ║ → first touch · set by marketing · never changes ║ ║ ║ ║ Aon Connect field: lead_source ║ ║ → current value · set by sales rep · can change ║ ║ ║ ║ SAME LEAD. DIFFERENT FIELD. DIFFERENT ANSWER. ║ ╚═══════════════════════════════════════════════════════╝ │ ▼ ╔══════════════════════════════════════════════════════════════════════════════╗ ║ DATABRICKS · MARKETING DATA LAKE · UNITY CATALOG · GOLD ZONE ║ ╠═══════════════════╦══════════════════╦═════════════════╦════════════════════╣ ║ lead_attributes_it ║ opportunity_ ║ cmpgn_ ║ sys_cvent_event ║ ║ ║ attributes_iit ║ campaigns_it ║ ║ ║ lead_id ║ opty_lead_id ║ campaign_id ║ Event_Code ║ ║ lead_source ║ opty_amount_usd ║ cvent_event_code ║ Event_Start_Date ║ ║ lead_status_code ║ opty_created_date ║ ║ ← Cvent 5-hop ║ ║ lead_stage ║ ║ ║ join to opp ║ ║ C_Lead_Source___ ║ lead_id ║ ║ undocumented ║ ║ Original1 ║ = opty_lead_id ║ ║ ║ ║ ║ (join key) ║ ║ ║ ║ lead_comverted_ ║ ║ ║ ║ ║ date ← typo(1n) ║ ║ ║ ║ ╠═══════════════════╩══════════════════╩═════════════════╩════════════════════╣ ║ MISSING: no is_mql flag · no agreed lead_source allowlist ║ ║ no documented Cvent join · spend data lives in Hive9 (outside MDL)║ ╚══════════════════════════════════════════════════════════════════════════════╝
Two ALTER COLUMN COMMENT statements encode the agreed rules directly in Unity Catalog. Any tool that reads schema metadata — Genie, Power BI, SQL Analyst — immediately inherits the definition.
-- ── Attribution allowlist — agreed Oct 2026, CMO sign-off ────────── ALTER TABLE aon_mdl_test.marketing.lead_attributes_it ALTER COLUMN lead_source COMMENT 'Agreed allowlist for marketing-sourced attribution (Oct 2026): Event, Content Syndication, Paid Social, Webinar, Email Campaign. Use Eloqua C_Lead_Source___Original1 (first-touch), NOT this field, when computing marketing_sourced_pipeline. Any value outside the allowlist is attributed to Sales / Other.'; -- ── MQL derivation rule — no is_mql flag exists in MDL ───────────── ALTER TABLE aon_mdl_test.marketing.lead_attributes_it ALTER COLUMN lead_status_code COMMENT 'MQL derivation rule (agreed Oct 2026): A lead is MQL when lead_status_code = QUALIFIED AND lead_stage = MQL. No pre-built is_mql flag exists. Always use both fields together. SQL also includes leads at Sales_Accepted status (not just Converted).'; -- ── Eloqua first-touch source — authoritative for attribution ─────── ALTER TABLE aon_mdl_test.marketing.eloqua_contacts ALTER COLUMN C_Lead_Source___Original1 COMMENT 'First-touch lead source captured by Eloqua at lead creation. This is the authoritative field for marketing attribution — NOT lead_source from Aon Connect (which reflects sales-rep updates). Allowlist: Event · Content Syndication · Paid Social · Webinar · Email Campaign';
Two Metric View YAML files. Requires Databricks Runtime 17.2+ and Unity Catalog. Deploy with databricks unity-catalog metric-views create --file <file>.
name: mv_marketing_pipeline
catalog: aon_mdl_test
schema: marketing
comment: >
Marketing pipeline and MQL metrics for AON MDL.
Encodes the agreed attribution allowlist (Oct 2026) and MQL
derivation rule so every BI tool returns identical numbers.
source:
table: marketing.lead_attributes_it
alias: l
joins:
- table: marketing.opportunity_attributes_iit
alias: o
on: "l.lead_id = o.opty_lead_id"
type: LEFT
- table: marketing.eloqua_contacts
alias: ec
on: "l.lead_id = ec.lead_id"
type: LEFT
measures:
- name: marketing_sourced_pipeline
expr: >
SUM(CASE WHEN ec.C_Lead_Source___Original1 IN
('Event','Content Syndication','Paid Social','Webinar','Email Campaign')
THEN o.opty_amount_usd ELSE 0 END)
synonyms: ["marketing pipeline","mktg pipeline","marketing sourced revenue"]
- name: mql_volume
expr: >
COUNT(DISTINCT CASE
WHEN l.lead_status_code='QUALIFIED' AND l.lead_stage='MQL'
THEN l.lead_id END)
synonyms: ["MQLs","qualified leads","marketing qualified leads"]
- name: mql_to_sql_conversion_rate
expr: >
ROUND(100.0 *
COUNT(DISTINCT CASE WHEN l.lead_stage='SQL' THEN l.lead_id END) /
NULLIF(COUNT(DISTINCT CASE
WHEN l.lead_status_code='QUALIFIED' AND l.lead_stage='MQL'
THEN l.lead_id END), 0), 1)
synonyms: ["conversion rate","MQL conversion","lead conversion"]
name: mv_event_attribution
catalog: aon_mdl_test
schema: marketing
comment: >
Event-to-pipeline attribution. Encodes the agreed 90-day window
(Oct 2026, CMO sign-off required to change) and the complete
five-hop Cvent join chain as a single governed measure.
source:
table: marketing.sys_cvent_event
alias: ev
joins:
- table: marketing.cmpgn_campaigns_it
alias: c
on: "ev.Event_Code = c.cvent_event_code"
type: LEFT
- table: marketing.campaign_member_it
alias: cm
on: "c.campaign_id = cm.campaign_id"
type: LEFT
- table: marketing.lead_attributes_it
alias: l
on: "cm.lead_id = l.lead_id"
type: LEFT
- table: marketing.opportunity_attributes_iit
alias: o
on: "l.lead_id = o.opty_lead_id"
type: LEFT
measures:
- name: post_event_pipeline_90d
expr: >
SUM(CASE WHEN o.opty_created_date
BETWEEN ev.Event_Start_Date
AND DATE_ADD(ev.Event_Start_Date, 90)
THEN o.opty_amount_usd ELSE 0 END)
synonyms: ["post-event pipeline","event pipeline","pipeline from event"]
comment: "90-day attribution window. CMO sign-off required to change."
- name: post_event_pipeline_30d
expr: >
SUM(CASE WHEN o.opty_created_date
BETWEEN ev.Event_Start_Date
AND DATE_ADD(ev.Event_Start_Date, 30)
THEN o.opty_amount_usd ELSE 0 END)
synonyms: ["30-day event pipeline"]
Python SDK setup. Requires databricks-sdk >= 0.28.0. Creates the Genie Space, loads both Metric Views, and installs the standing instructions that prevent Genie from re-deriving governed rules.
from databricks.sdk import WorkspaceClient from databricks.sdk.service.dashboards import ( GenieSpace, GenieSpaceDataset, GenieSpaceInstruction, GenieSpaceTrustedQuery ) w = WorkspaceClient() space = w.genie.create(GenieSpace( title="AON Marketing Data Lake — CE", warehouse_id="<your-sql-warehouse-id>", )) space_id = space.space_id for mv in ["mv_marketing_pipeline", "mv_event_attribution"]: w.genie.create_space_dataset(space_id=space_id, dataset=GenieSpaceDataset(display_name=mv, table=f"aon_mdl_test.marketing.{mv}")) INSTRUCTIONS = [ "ALWAYS use mv_marketing_pipeline for pipeline, revenue, or MQL questions.", "ALWAYS use mv_event_attribution for event or forum questions.", "For marketing-sourced pipeline use the marketing_sourced_pipeline measure. " "DO NOT filter on lead_attributes_it.lead_source — that is the Sales CRM field.", "For MQL counts use the mql_volume measure. DO NOT derive manually.", "For post-event pipeline use post_event_pipeline_90d. The 90-day window " "is agreed standard. CMO sign-off required to change it.", ] for text in INSTRUCTIONS: w.genie.create_space_instruction(space_id=space_id, instruction=GenieSpaceInstruction(instruction=text))