kimo
GuideBeginner20 minMarketing

Set up a unified marketing dashboard in a day

You can set up a unified marketing dashboard in one working day by doing six things in order: connect every source, map campaigns to a single channel list, normalize platform metrics into shared tables, define a handful of measures once, build one overview page with drill-downs, and add alerts. This guide walks through each hour, with the SQL, the measure definitions and the checks that keep the numbers honest.

Nadia Benali · Head of Product Marketing
20 min read

At a glance

Level
Beginner
Time
20 min

Prerequisites

  • Read access to your ad accounts, social accounts, GA4 and Search Console
  • Read access to your revenue system of record (CRM, shop or billing)
  • A Kimo workspace with the Marketing product enabled
  • An agreed reporting time zone and currency

You will end up with

One overview page that shows every channel against revenue, spend, MER and CAC, with drill-downs for social, search and paid, and alerts on pacing and tracking gaps.

What does a unified marketing dashboard include?

A unified marketing dashboard is one overview page that shows every channel your team runs (organic social, search, paid media, email and earned media) against the same business outcomes, with a drill-down page per channel. By the end of the day you will have:

  • All marketing sources connected and syncing on a schedule.
  • A channel mapping table that assigns every campaign to one of about ten channels.
  • Three normalized models: marketing_spend_daily, social_content_daily and web_outcomes_daily.
  • Shared measures for spend, sessions, key events, revenue, MER, CAC and engagement rate.
  • An overview page with six blocks and drill-downs for social, search and paid.
  • Alerts on spend pacing, tracking gaps and unmapped campaigns.

If you want the reasoning behind each design choice, read the whitepaper One View of Marketing. This guide is the hands-on companion. You can also start from the Marketing command center template, which ships the models and layout described here, and adapt it as you go.

~6 h
Hands-on time, plus first sync
3
Normalized models
8
Shared measures
1 + 3
Overview page plus channel drill-downs

Before you start: access and decisions

Most delays on setup day come from missing permissions, not technical problems. Collect access the day before, and make three decisions in writing so you do not relitigate them mid-build.

Access checklist

  • Admin or analyst access to each social account: Instagram professional account, Facebook Page, LinkedIn Page (admin role), X, YouTube channel, Pinterest business account, Threads.
  • Read access to ad accounts: Google Ads, Meta Ads, LinkedIn Campaign Manager, TikTok Ads.
  • Owner or full user on the Search Console property, and Viewer or higher on the GA4 property.
  • API key or OAuth access for your email platform (Mailchimp or Brevo).
  • Export or API access to your media monitoring tool.
  • Read access to the revenue system of record: CRM (for example HubSpot) or shop backend (for example Shopify), or a read-only database user.
DecisionOptionsOur default
Reporting time zone and week startCompany HQ time; UTCHQ time zone, weeks start Monday
Revenue system of recordBilling, CRM closed-won, shop ordersWhichever finance reconciles to each month
Reporting currencySingle currency; per-marketOne currency, converted daily with a dated rate table
Three decisions to write down before connecting anything.

Hour 1: Connect every source

Connect sources in order of business impact: revenue first, then paid media, then analytics and search, then social, email and earned media. Revenue comes first because every other number is eventually checked against it.

The sources this guide connects. Swap HubSpot or Shopify for your own revenue system.
  1. Step 1:

    Connect the revenue source

    In Connectors, add your CRM or shop. If revenue lives in your own Postgres or MySQL database and should not leave your network, connect it through Kimo Bridge so queries run in place.

  2. Step 2:

    Connect ad platforms with 25 months of history

    Add Google Ads, Meta Ads, LinkedIn Ads and TikTok Ads. Request at least 25 months so you can compare year over year and, later, fit a media mix model.

  3. Step 3:

    Connect GA4 and Search Console

    Add GA4 and Search Console. The Search Console setup doc explains property types. Search Console retains 16 months of data4, so backfill as soon as possible and keep the history in Kimo from then on.

  4. Step 4:

    Connect social, email and earned media

    Add each organic social account, your email platform and your media monitoring export. These sources rarely carry revenue, but they explain changes in branded search and direct traffic.

  5. Step 5:

    Set sync schedules

    Daily syncs are enough for most marketing data; ad spend can sync hourly if you pace budgets intraday. See sync schedules for options.

Hour 2: Map every campaign to one channel list

Spend lives in ad platforms, sessions in analytics and revenue in your CRM. The only bridge between them is campaign naming, usually the utm_source, utm_medium and utm_campaign values on your links. Start by agreeing on a short channel list, then write rules that assign every source and medium pair to exactly one channel.

Align your rules with GA4’s default channel groups wherever possible, so your dashboard and GA4 tell the same story. For example, GA4 classifies traffic as Paid Social when the source matches a known social site and the medium matches the regular expression ^(.*cp.*|ppc|retargeting|paid.*)$, and as Email when the source or medium is email, e-mail, e_mail or e mail1. Keep your extensions (for example, separating partner newsletters from owned email) explicit.

channel_map.sql: one channel per source/medium pair
sql
select
    lower(trim(source)) as source,
    lower(trim(medium)) as medium,
    case
        when lower(medium) in ('email', 'e-mail', 'e_mail', 'e mail')
            or lower(source) in ('email', 'e-mail', 'e_mail', 'e mail')
            then 'Email'
        when lower(source) in ('google', 'bing')
            and regexp_like(lower(medium), '^(.*cp.*|ppc|retargeting|paid.*)$')
            then 'Paid search'
        when lower(source) in ('facebook', 'instagram', 'linkedin', 'tiktok', 'x', 'pinterest', 'youtube')
            and regexp_like(lower(medium), '^(.*cp.*|ppc|retargeting|paid.*)$')
            then 'Paid social'
        when lower(medium) = 'organic' then 'Organic search'
        when lower(medium) in ('social', 'social-network', 'social-media', 'sm')
            or lower(source) in ('facebook', 'instagram', 'linkedin', 'x', 't.co', 'pinterest', 'youtube', 'threads')
            then 'Organic social'
        when lower(medium) in ('display', 'banner', 'cpm') then 'Display'
        when lower(medium) in ('pr', 'press', 'earned') then 'Earned media'
        when lower(medium) = 'referral' then 'Referral'
        when source = '(direct)' then 'Direct'
        else 'Unmapped'
    end as channel
from web_sessions_raw
group by 1, 2

Note that the rule order matters: the email rule runs first so a newsletter sent from a social scheduling tool is not misclassified, and paid rules run before organic rules so facebook / cpc lands in Paid social. Test the mapping by listing the twenty largest source and medium pairs and checking each one by eye.

Hour 3: Normalize platform metrics

Each platform exports different field names and defines engagement differently. LinkedIn’s organization statistics compute engagement as clicks, likes, comments and shares over impressions2. Instagram’s media insights count total interactions as likes, saves, comments and shares, and mark impressions as deprecated for media created after July 2, 2024 in favor of views3. The fix is to import components, rename them to canonical columns and recompute every ratio yourself.

social_content_daily.sql: one row per platform, account and day
sql
-- Canonical columns: views (delivery), reach, engagements (no clicks), link_clicks
select date, 'instagram' as platform, account_id,
       views,
       reach,
       likes + comments + shares + saves            as engagements,
       coalesce(link_clicks, 0)                     as link_clicks
from instagram_media_daily
union all
select date, 'linkedin-pages', organization_id,
       impression_count                             as views,
       unique_impressions_count                     as reach,
       like_count + comment_count + share_count     as engagements,
       click_count                                  as link_clicks
from linkedin_share_stats_daily
union all
select date, 'facebook', page_id,
       views, reach,
       reactions + comments + shares                as engagements,
       link_clicks
from facebook_page_posts_daily
union all
select date, 'x', account_id,
       impressions, null                            as reach,
       likes + replies + reposts + bookmarks        as engagements,
       url_clicks
from x_posts_daily
union all
select date, 'youtube', channel_id,
       views, null,
       likes + comments + shares                    as engagements,
       0
from youtube_channel_daily

Two details are easy to miss. First, reach is set to null where a platform does not report distinct accounts at the grain you need; a null is honest, a zero is wrong. Second, reach is never summed across platforms in later steps, because each platform de-duplicates only its own audience.

marketing_spend_daily.sql: spend in one currency, mapped to channel
sql
select s.date,
       s.platform,
       s.campaign_name,
       m.channel,
       s.spend * fx.rate                                as spend,
       s.impressions,
       s.clicks
from (
    select date, 'google-ads' as platform, campaign_name, currency, cost as spend, impressions, clicks from google_ads_campaign_daily
    union all
    select date, 'meta-ads', campaign_name, currency, spend, impressions, clicks from meta_ads_campaign_daily
    union all
    select date, 'linkedin-ads', campaign_name, currency, cost_in_local_currency, impressions, clicks from linkedin_ads_campaign_daily
    union all
    select date, 'tiktok-ads', campaign_name, currency, spend, impressions, clicks from tiktok_ads_campaign_daily
) s
left join fx_rates_daily fx
    on fx.date = s.date and fx.from_currency = s.currency and fx.to_currency = 'USD'
left join campaign_channel_map m
    on m.campaign_name = lower(s.campaign_name)

The third model, web_outcomes_daily, joins GA4 sessions and key events by date, source and medium to the channel map, and adds orders or pipeline from the revenue system by the same keys. If you export GA4 to BigQuery, use the daily tables rather than the intraday streaming tables for attribution fields; Google notes that streaming export omits user-attribution fields (campaign, source, medium) for new users, and that user-attribution data for existing users needs about 24 hours to fully process5.

Hour 4: Define measures once

Measures are the numbers people will quote. Define each once, with a description and an owner, so the overview, the drill-downs and every Ask Kimo answer use the same formula. Eight measures cover most needs.

models/marketing_overview.yml
yaml
model: marketing_overview
owner: marketing-ops
grain: date, channel
measures:
  spend:
    type: sum
    sql: spend
    format: currency
    description: Media spend in USD, all paid platforms
  sessions:
    type: sum
    sql: sessions
  key_events:
    type: sum
    sql: key_events
    description: Sign-ups and demo requests (GA4 key events)
  revenue:
    type: sum
    sql: revenue
    format: currency
    description: Net revenue from the system of record, refunds removed
  new_customers:
    type: count_distinct
    sql: customer_id
    filters: [is_first_order = true]
  mer:
    type: ratio
    numerator: revenue
    denominator: spend
    format: multiplier
    description: Total revenue / total marketing spend, all channels
  cac:
    type: ratio
    numerator: spend
    denominator: new_customers
    format: currency
  engagement_rate:
    type: ratio
    numerator: engagements
    denominator: views
    format: percent
    description: Reactions, comments, shares, saves over views. Clicks excluded

Read the glossary entries for MER, CAC and engagement rate if your team uses different variants. The important part is not which variant you choose but that you choose one and write it into the measure description. If paid CAC and blended CAC both matter, define both with distinct names.

Hour 5: Build the overview and drill-downs

Build one overview page that answers "what did marketing produce this week, and at what cost?" in under a minute, then one drill-down per channel family for depth. Use the same date filter and comparison period on every page.

BlockTilesQuestion it answers
Outcome stripRevenue, new customers, spend, MER, CAC (vs prior period and target)Are we on track?
Channel tableSpend, sessions, key events, revenue by channel, plus UnmappedWhere did results come from?
Paid efficiencySpend and CPA by platform; pacing vs budgetIs paid spend working and on pace?
Organic socialViews, reach and engagement rate per networkIs content resonating?
SearchSearch Console clicks and impressions; GA4 organic sessionsIs search demand growing?
Earned and emailMentions, share of voice, email clicksAre we being talked about and read?
Overview layout, top to bottom.
Sessions by channel, weekly
  • Organic search
  • Paid
  • Organic social
  • Email
Figure. Illustrative data: what the channel trend tile looks like once mapping is in place. Simulated numbers.

For drill-downs, the social media overview and SEO funnel templates are ready-made. The paid drill-down needs only a campaign table with spend, clicks, key events and CPA, sortable by spend. You can see the finished result on simulated data in the command center.

Hour 6: Add alerts and share

Alerts turn the dashboard from something people check into something that tells them when to look. Start with four, each routed to the person who can act.

AlertConditionOwner
Spend pacingMonth-to-date spend > 110% of the pro-rated budgetPaid lead
Tracking gapSessions from any channel drop > 40% day over dayMarketing ops
Unmapped trafficUnmapped sessions > 5% of total for the weekMarketing ops
Sync freshnessAny source older than 36 hoursDashboard owner
Starter alerts.

Configure them in Alerts (see the alerts docs), then share the overview with a scheduled weekly snapshot to the team channel. Pin the definitions page so newcomers can see how each number is built.

How do you check the numbers before sharing?

Reconcile three totals before anyone outside the build team sees the dashboard. Small gaps are expected; large ones point to a mapping or currency bug.

CheckCompare againstAcceptable gapCommon cause of larger gaps
Total spendPlatform invoices for last full monthUnder 2%Currency conversion; missing ad account
SessionsGA4 Traffic acquisition report, same datesUnder 1%Time zone mismatch; filters in GA4 views
RevenueFinance month-end figureUnder 1%Refunds, taxes or test orders included
Search clicks vs organic sessionsTrend onlyLines move togetherConsent, bot filtering, other search engines in GA4
Reconciliation targets. Thresholds are pragmatic starting points, not standards.

Search Console clicks and GA4 organic sessions will never match exactly: Search Console counts clicks on Google, while GA4 counts sessions only when the tag fires and includes other search engines in Organic Search. Our guide to SEO reporting with Search Console and GA4 covers the join in detail.

Troubleshooting

Paid social shows up as organic social

Your ad links are missing a paid medium, or the medium value does not match the paid pattern. Check the Meta and LinkedIn URL parameters fields, and make sure the medium is something like paid_social or cpc, not social.

Google Ads traffic appears as (not set)

Check that auto-tagging is enabled and that the Google Ads account is linked to the GA4 property. When both auto-tagging and manual UTM tags are present, GA4 prioritizes auto-tagging7, so manual tags on Google Ads links are optional.

The sum of channel revenue is larger than total revenue

You are summing platform-attributed revenue. On the overview, channel revenue must come from one attribution rule applied to orders in your system of record. Keep platform-reported conversions on the paid drill-down only.

Engagement rate jumped overnight for one network

Check for a platform definition change, such as a metric being renamed or deprecated. Add an annotation with the effective date, and if possible keep both the old and new series for a few weeks.

Sources

7 references
  1. [GA4] Default channel group (opens in a new tab)
    Google Analytics Helpsupport.google.com

    Rules for Paid Social, Organic Social, Email and other default channels.

  2. Organization Share Statistics (opens in a new tab)
    Microsoft Learn (LinkedIn Marketing API)learn.microsoft.com

    Engagement = organic clicks, likes, comments and shares over impressions; unique impressions field.

  3. Instagram Media Insights (API reference) (opens in a new tab)
    Meta for Developersdevelopers.facebook.com

    Views, reach and total_interactions; impressions deprecated for media created after July 2, 2024.

  4. Connect Search Console to Google Analytics (opens in a new tab)
    Google Analytics Helpsupport.google.com

    Search Console keeps 16 months of data; data appears 48 hours after collection.

  5. [GA4] BigQuery Export (opens in a new tab)
    Google Analytics Helpsupport.google.com

    Daily vs streaming export; streaming omits user-attribution fields for new users; ~24 hours to process attribution data.

  6. Mail Privacy Protection & Privacy (opens in a new tab)
    Appleapple.com

    Remote content downloaded in the background by default.

  7. About auto-tagging (opens in a new tab)
    Google Ads Helpsupport.google.com

    GCLID auto-tagging; prioritized over manual tagging in GA4.

External sources were accessed at the time of writing. Kimo product details, customers and figures in examples are illustrative unless a source is cited.

0%

Mark as done

0 of 10 sections done

Frequently asked questions

Can I really build a unified marketing dashboard in one day?

Yes, if access is collected beforehand and you start from a template. The day covers connection, mapping, normalization, measures, the overview and alerts. Expect a second, shorter session the following week to fix mapping gaps the first real data reveals.

Which metrics belong on the overview page?

Revenue or pipeline, new customers, spend, MER and CAC at the top; then spend, sessions, key events and revenue by channel. Platform-specific metrics such as reach and engagement rate belong in channel blocks, not in cross-channel totals.

Should I use GA4 channel groups or my own?

Start from GA4’s default channel group rules so your numbers agree with GA4, then add explicit extensions such as Earned media or Partner newsletters. Document every rule you add.

How do I handle multiple currencies?

Convert at transaction or daily level using a dated exchange-rate table, in the model rather than in charts. Keep the original currency column so finance can audit the conversion.

Do I need a data warehouse first?

No. Kimo syncs sources into its managed cloud by default, and Kimo Bridge can query databases that must stay on your own servers. If you already have a warehouse such as BigQuery, you can connect it and model on top of it.

Put it to work

Skip the setup — start from a working version.

Marketing command center: Every channel on one screen: social, SEO, paid, email and media.

All resources
Whitepaper
Marketing

One View of Marketing

Unified measurement across social, search, paid and earned media, in the age of AI search.

Nadia Benali
24 pages

Every channel. One dashboard.

Social, SEO, paid, email, PR and AI-search visibility, normalized into one command center your whole team reads the same way.