Skip to content

Customer Dashboard — Marketing ​

The Marketing section (/marketing) is a lead-source attribution dashboard: it rolls up where leads came from (Manual, Meta/Facebook Lead Ads, Google, imports) and how each source converts, so a customer can judge channel ROI.

Marketing was moved out of the CRM group into its own top-level sidebar item, but it still rides the same entitlement key (crm.marketing / FEATURES.CRM_MARKETING) and the same crm RBAC resource — only the placement changed (see CustomerLayout.tsx).

Screenshots ​

Marketing — lead-source attribution dashboard

Architecture Overview ​

How It Works (Step-by-Step) ​

  1. Open /marketing. The page is gated by crm.marketing (sub-section) + requirePermission("crm","view"). Without the entitlement the sidebar item hides.
  2. Attribution rollups. The dashboard calls GET /api/leads/marketing-stats (crmLead.controller.getMarketingStats), which aggregates leads by source / UTM attribution across the selected range. Journey rollups come from GET /api/leads/journey-stats (getJourneyStats), reading CrmLeadJourney.
  3. Meta / Facebook Lead Ads feed marketing. When facebook_meta is on, metaLeadAds.routes.ts manages Pages, Lead Gen Forms, field mapping, and sync. New Meta leads land in CrmLead with their source/attribution set, and each sync writes a LeadSyncHistory row shown in the sync log. These routes are admin/superadmin-gated.
  4. AI Insights (optional). When the lead_analytics entitlement is granted, GET /api/leads/ai-insights returns AI-synthesized lead analytics over a scope (account/segment/campaign) and range, plus smart actions that can create a segment. (The AI Insights page is a CRM child; it reuses the same analytics endpoints referenced from Marketing.)

⚠️ Unverified: the Marketing page has a single screenshot (Marketing/1.png) and its exact card layout was not read from the page component. The endpoint mapping above is derived from the marketing-stats / journey-stats routes and the Meta Lead Ads routes; treat specific card labels as indicative.

File Reference ​

FileRoleKey Functions
app/src/layouts/CustomerLayout.tsxMarketing nav item (/marketing, crm.marketing)mainNavItems Marketing group
routes/crmLead.routes.tsMarketing + journey + AI-insights endpoints/api/leads/marketing-stats, /journey-stats, /ai-insights
controllers/crmLead.controller.tsAttribution rollupsgetMarketingStats, getJourneyStats
controllers/leadAnalytics.controller.tsAI insights + smart actionsgetAiInsights, getSmartActions, createSegmentFromSmartAction
routes/metaLeadAds.routes.tsMeta Pages/Forms/sync (feeds attribution)listPages, syncForm, listSyncHistory
controllers/metaLeadAds.controller.tsMeta sync logicsyncForm, saveFormFieldMapping

Data Model ​

CollectionWhy it existsKey fields
CrmLeadSource/attribution per leadsource, UTM/attribution fields, customerUID
CrmLeadJourneyCross-channel journey eventsjourney steps, timestamps
LeadSyncHistoryRecord of each Meta/Google sync runprovider, formId, counts
LeadFieldMapping / CrmFieldMappingMap external form questions → CRM columnssource field → target field
MetaConnection / MetaPageSubscriptionMeta app connection + subscribed pagestokens, pageId

API Endpoints ​

Marketing attribution stats ​

  • Method: GET
  • Path: /api/leads/marketing-stats
  • Auth: verifyJwt → requireFeatureAccess(leads) → resolveCrmLeadScope → requireLeadPermission("view")
  • Response: 200 with lead counts/conversions grouped by source.

Journey stats ​

  • Method: GET
  • Path: /api/leads/journey-stats
  • Auth: same lead view chain.

AI insights ​

  • Method: GET
  • Path: /api/leads/ai-insights
  • Auth: lead view + lead_analytics feature.

Meta: list pages / sync a form ​

  • GET /api/meta/pages, POST /api/meta/forms/:formId/sync, GET /api/meta/sync-history
  • Auth: verifyJwt → requireFeatureAccess(facebook_meta) → resolveCrmLeadScope (admin/superadmin bar).

External Integrations ​

  • Meta (Facebook/Instagram) Lead Ads — Pages + Lead Gen Forms sync into leads via the Conversions API / Lead webhook. Shares the org's Meta app with WhatsApp. Failures are recorded in LeadSyncHistory; the "needs matching" alert surfaces unmapped form questions.
  • Google Ads — offline conversions / Lead Form capture when google_ads is on (configured in Connecter).

How to Test (End-to-End) ​

  1. Grant crm.marketing; open /marketing and confirm attribution cards render.
  2. Create leads with different source values → confirm the source breakdown updates.
  3. With facebook_meta on, connect a Page, subscribe a form, then sync → confirm new leads appear with source=meta and a LeadSyncHistory entry.
  4. With lead_analytics on, open AI Insights and generate for a scope → confirm smart actions can create a segment.

Troubleshooting ​

SymptomCauseFix
Marketing hiddencrm.marketing sub-section offGrant the Marketing sub-section
No Meta leadsPage not subscribed or form sync disabledSubscribe the Page, enable form sync, run a manual sync
"Fields need matching" alertForm questions not mapped to columnsOpen the Match fields dialog and map them
AI Insights lockedlead_analytics entitlement offGrant AI Insights (superadmin → org → customer)

Last updated: