2026-06-08 clicks (rebrandly) attribution issues

Report for creator-campaign click attribution (moises_report.campaigns_funnel_creators → Tableau "Creators Campaigns"). It documents what the dashboard numbers represent and traces exactly where the 2024 YouTube ~16k comes from.
Last update: 2026-06-15

TL;DR. The 2024 clicks "crater" is not a tracking bug — confirmed by independent validation (2026-06-12). The dashboard's ~16k is the YouTube-only slice of clicks, and the 2023→2024 drop is a real year-over-year decline in YouTube creator activity (Instagram overtook YouTube in 2024; 2025 partly recovered). Clicks are correctly attributed (~84% of 2024, via the slug→sheet fallback) — see the step-by-step funnel below. The separate 2025 installs collapse is a platform-attribution problem (iOS/Android), a different pipeline.

The 3 points

1) Two different bugs are stacked in the dashboard

YearSymptom on dashboardRoot causeLayer
2024YouTube clicks 145k → 16kNot a bug: real YoY decline in YouTube creator activity; the dashboard series is YouTube-only (clicks are correctly attributed — see funnel below)clicks
2025Installs collapse 35k → 684 ⚠️iOS AdAttributionKit (Apr 2025) + Android UTM break (Aug 2025)installs (separate pipeline)

Don't conflate them. The campaign_utm_ct investigation explains only the 2024 clicks. The 2025 installs collapse is platform attribution, which will be linked from the platform source pages once those are curated.

Resolved (2026-06-12, independently validated): the 2024 clicks number is not a tracking bug. Production attributes ~84% of 2024 clicks via the slug→creators-sheet fallback; the dashboard's 16k is the YouTube-only slice; the drop is a real YoY decline. The step-by-step funnel below shows exactly where the 16k comes from. (Earlier this section read "OneLink → campaign_utm_ct NULL"; that NULL is expected and recovered downstream.)

2) How clicks are attributed — parser vs the slug→sheet fallback

campaigns_funnel_clicks attributes a click via LOWER(COALESCE(campaign_utm_ct, creators.campaign)) — first the campaign parsed from the URL (campaign_utm_ct), then a fallback join of the link's slug (route_slashtag) to the creators sheet. The 2024 OneLink links return NULL from the parser, but the slug→sheet fallback recovers them — and that fallback is already live in production. The table shows what each layer contributes; it is not a gap to fix.

First-session human clicks by link-creation year — parser alone vs production (parser + slug→sheet fallback):

Link yearClicksParser only+ slug→sheet fallbackProduction (attributed)Still unattributed% parser → % production
2021555,457522,607+237522,84432,61394.1% → 94.1%
2022623,655525,676+87,939613,61510,04084.3% → 98.4%
2023216,213214,194+218214,4121,80199.1% → 99.2%
202469,28326,726+32,77859,5049,77938.6% → 85.9%
2025231,91157,313+10,63167,944163,96724.7% → 29.3%
2026*1,080325+7191,0443630.1% → 96.7%

qmb: session rebrandly-report-refresh-2026-06-15 · job qmb_2026-06-15_13-47-40_d138a7 (table) · qmb_2026-06-15_13-47-50_5aff93 (2025 composition)

3) Why the dashboard's 16k is smaller than the production total

The tables here and the Tableau dashboard measure different universes — don't compare 1:1.

These tables (production clicks)Tableau "Posts YT" dashboard
UniverseALL attributed clicks (every platform + generic links)Creator-sheet campaigns, YouTube only
Grouped byLink-creation year (route_created_at)Campaign publication year (YouTube publish date)
DedupOne row per first-session clickPer-campaign click de-dup inside the workbook
Sourcederived_marketing_master.rebrandly + creators sheetmoises_report.campaigns_funnel_creators

So the dashboard's ~16k is the YouTube slice of production clicks, not a gap — the step-by-step funnel below shows the exact narrowing (all platforms → YouTube). Reproducing the funnel from campaigns_funnel_creators matches the dashboard on 2025/2026 (installs 687≈684, 9=9; purchases 113=113), confirming it's the same funnel — but 2020–2023 differ because the dashboard's "Ano de publicação" is the YouTube publish date (not the sheet's post_date), with per-campaign click de-duping inside the Tableau workbook.

Funnel lineage (green = working, red = broken)

graph LR utm["campaign_utm_ct (rebrandly)
NULL for OneLink — expected"] sheet["creators sheet (slashtag)
fallback — recovers OneLink"] subgraph CLICKS["clicks layer — working"] cfc["campaigns_funnel_clicks
COALESCE(utm_ct, sheet slashtag) → ~86% of 2024"] end subgraph INSTALLS["installs layer — broken (separate 2025 bug)"] ios["itunes_connect_installs"] andr["android_installs"] web["web_installs"] cfi["campaigns_funnel_installs"] end cf["campaigns_funnel (master)"] rep["campaigns_funnel_creators
moises_report → Tableau"] utm --> cfc sheet --> cfc ios --> cfi andr --> cfi web --> cfi cfc --> cf cfi --> cf cf --> rep classDef broken fill:#ffd6d6,stroke:#c00,color:#000 classDef ok fill:#ddf4e4,stroke:#2da44e,color:#000 class ios,andr,web,cfi broken class utm,sheet,cfc,cf,rep ok
⚠️ Two date dimensions — read this before comparing years The tables below bucket rows by year using two different dates. They usually coincide, but the distinction matters:
  • Link-creation year (rebrandly.route_created_at) — when the Rebrandly short link was created. Every clicks number on this page uses this (the funnel, the by-year table, and the clicks column of "Posts vs clicks"), so all click totals reconcile (e.g. YouTube 2024 = 16,844 everywhere).
  • Post-date year (connected_sheets.mkt_creators_campaigns.post_date) — when the creator published the content. The posts count uses this, because the creators sheet carries no link-creation date.
A campaign's link is usually created the same year its content is posted, so the two line up closely; they diverge only when a link is created in a different calendar year than the post. The Tableau dashboard uses a third axis — YouTube publish date — which is why its yearly buckets don't match 1:1 either.

Where the 2024 YouTube ~16k comes from — clicks funnel, step by step

Each row is a stage of the clicks pipeline, from the raw Rebrandly click stream down to the ~16k YouTube number on the Tableau dashboard. The counts are deduped first-session-aware clicks for the 2024 link-creation cohort (one row per real click), so each drop is a single, explainable filter — not data loss. Validated independently (fable, 2026-06-12). Numbers as of 2026-06-15 (qmb session rebrandly-clicks-funnel-report-2026-06-15, job qmb_2026-06-15_10-02-34_37160d); frozen reference snapshot.rebrandly_20260612. They drift slightly upward with daily ingestion; the proportions are stable.

#Stage (model)Filter applied here2024 clicks% of rawDropped here · what it is
1rebrandly_prep (raw)all click events for 2024-created links124,652100%— (baseline)
2rebrandly (master)agent_type = 'human'94,90476.1%−29,748 · bot/robot clicks
3campaigns_funnel_clicks (grain)client_session_first IS TRUE69,28655.6%−25,618 · repeat clicks within a session (1 click/session)
4campaigns_funnel_clicks (attribution)COALESCE(campaign_utm_ct, creators.campaign) IS NOT NULL59,50747.7%−9,779 · unattributable (no URL campaign & slug not in sheet — incl. the Eloy Casagrande artist campaign ~6.4k, missing from the sheet)
5campaigns_funnel_creatorsslug matches a creators-sheet campaign36,51329.3%−22,994 · attributed but non-creator / generic campaigns (e.g. br_moisesapp, bf24*, download)
6Tableau "Posts YT"platform = 'YouTube'16,84413.5%−19,669 · other-platform creator clicks (Instagram 18,149, other 1,517)

So the dashboard's ~16k is reached by stacked, expected filters — no missing ~53k and no downstream leak. The two biggest drops are repeat-session clicks (step 3) and non-YouTube platforms (step 6, Instagram is actually larger than YouTube in 2024). Independent validation reproduced this on three axes (link-year, post-date year, and the creators sheet's own campaign counts).

Code-review notes for the dbt funnel port (two real bugs in the as-deployed Dataform campaigns_funnel_clicks, surfaced during validation): (1) the slug→sheet LEFT JOIN is against the un-deduped moises_raw sheet, so clicks whose slug matches multiple campaigns are double-counted (~+16.6% in 2024) — the dbt port must dedupe the join (the counts above are already deduped). (2) it extracts the slug with SPLIT(link,'/')[OFFSET(1)], which returns empty for protocol-prefixed sheet links (https://moises.app/…) and misses ~1,525 clicks — use the last non-empty path segment. As-deployed 2024 attribution is ~83.7%; with the slug-extraction fix it is ~85.9%.

Guardrail: the dbt test assert_rebrandly_new_links_attributable (warn) lists recent links that are neither URL-attributable nor in the creators sheet — a review queue for the sheet-completeness gap (e.g. the Eloy Casagrande links above). Interpreting and alerting on it is tracked as agent-driven attribution alerts.

Creator clicks by year & platform (the YouTube → Instagram shift)

First-session clicks attributed to a creators-sheet platform, by link-creation year. This is the series behind the dashboard's 2024 "crater": YouTube peaked in 2023 and collapsed in 2024 (then partly recovered in 2025); Instagram peaked in 2022 and also declined — 2024 is simply the year Instagram overtook YouTube, not a year Instagram grew. Source for the Metabase query below.

Link yearYouTubeInstagramTikTok
2021100,786680
2022124,005165,42910,626
2023140,96833,8791,702
202416,84418,1490
202546,053971137
20268152130

qmb: session rebrandly-clicks-funnel-report-2026-06-15 · job qmb_2026-06-15_10-02-54_6572b6

Posts vs clicks, with year-over-year change

Creator posts next to Rebrandly clicks, with YoY % for each. This is the richer story behind the clicks chart: the team kept posting more on Instagram/TikTok while Rebrandly clicks on those platforms collapsed — YouTube is the only one where clicks track posts. Clicks use the same link-creation-year basis as the table above, so they reconcile (YouTube 2024 = 16,844 in both). Numbers as of 2026-06-15.

PlatformYearPostsPosts YoYClicksClicks YoY
YouTube202235−44%124,005+23%
2023102+191%140,968+14%
202432−69%16,844−88%
202575+134%46,053+173%
2026*9−88%815−98%
Instagram202257165,429
202376+33%33,879−80%
2024158+108%18,149−46%
2025367+132%971−95%
2026*158−57%213−78%
TikTok20222810,626
20239−68%1,702−84%
202434+278%0−100%
2025104+206%137
2026*76−27%0−100%

qmb: session rebrandly-report-refresh-2026-06-15 · job qmb_2026-06-15_14-57-42_e1181f

Reproduce with qmb

recoverability: session pi-2026-06-08-rebrandly-recoverability

funnel reproduction: session pi-2026-06-09-tableau-funnel-numbers

step funnel + by-year×platform: session rebrandly-clicks-funnel-report-2026-06-15 (jobs qmb_2026-06-15_10-02-34_37160d, qmb_2026-06-15_10-02-54_6572b6, qmb_2026-06-15_10-20-09_f2e2af)

Clicks by year & platform — Metabase query

First-session creator clicks by link-creation year and platform (YouTube / Instagram / TikTok / …), with a bucket for non-creator / unattributed links so totals reconcile. Drop this into Metabase and pivot platform as the series. For the "posts" axis instead of link-creation, swap EXTRACT(YEAR FROM r.route_created_at_timestamp) for the sheet's post_date year (join the sheet's MAX(post_date) per slug).

WITH sheet AS (
  -- one platform per Rebrandly slug from the creators sheet (last non-empty path segment)
  SELECT slug, ANY_VALUE(platform) AS platform
  FROM (
    SELECT
      LOWER(SPLIT(link_rebrandly, '/')[SAFE_OFFSET(ARRAY_LENGTH(SPLIT(link_rebrandly, '/')) - 1)]) AS slug,
      platform
    FROM `data-platform-production-3573.connected_sheets.mkt_creators_campaigns`
    WHERE campaign IS NOT NULL AND link_rebrandly IS NOT NULL
  )
  GROUP BY slug
)
SELECT
  EXTRACT(YEAR FROM r.route_created_at_timestamp) AS link_year,
  COALESCE(s.platform, 'Unattributed / non-creator') AS platform,
  COUNT(*) AS first_session_clicks
FROM `data-platform-production-3573.derived_marketing_master.rebrandly` r
LEFT JOIN sheet s ON s.slug = LOWER(r.route_slashtag)
WHERE r.client_session_first IS TRUE
GROUP BY link_year, platform
ORDER BY link_year, platform

Posts + clicks + YoY% — query

session rebrandly-report-refresh-2026-06-15 · job qmb_2026-06-15_14-57-42_e1181f

Posts = distinct creator campaigns by post_date year (no link required). Clicks = first-session clicks by link-creation year (route_created_at), platform via the slug → creators-sheet map — the same basis as the by-year clicks table, so the two reconcile. YoY % is a LAG over year per platform; pre-2022 %s are off a tiny base, so the table above starts at 2022.

WITH base AS (
  SELECT campaign, platform, post_date, link_rebrandly
  FROM `data-platform-production-3573.connected_sheets.mkt_creators_campaigns`
  WHERE campaign IS NOT NULL AND platform IN ('YouTube', 'Instagram', 'TikTok')
),
posts AS (                                    -- posts by post-date year (no link required)
  SELECT EXTRACT(YEAR FROM post_date) AS yr, platform, COUNT(DISTINCT campaign) AS posts
  FROM base WHERE post_date IS NOT NULL GROUP BY yr, platform
),
slug_plat AS (                                -- slug -> platform (one platform per slug)
  SELECT LOWER(SPLIT(link_rebrandly, '/')[SAFE_OFFSET(ARRAY_LENGTH(SPLIT(link_rebrandly, '/')) - 1)]) AS slug,
         ANY_VALUE(platform) AS platform
  FROM base WHERE link_rebrandly IS NOT NULL GROUP BY slug
),
clicks AS (                                   -- clicks by LINK-CREATION year (matches the by-year table)
  SELECT EXTRACT(YEAR FROM r.route_created_at_timestamp) AS yr, sp.platform, COUNT(*) AS clicks
  FROM `data-platform-production-3573.derived_marketing_master.rebrandly` r
  JOIN slug_plat sp ON sp.slug = LOWER(r.route_slashtag)
  WHERE r.client_session_first IS TRUE GROUP BY yr, sp.platform
),
merged AS (
  SELECT COALESCE(p.yr, c.yr) AS yr, COALESCE(p.platform, c.platform) AS platform,
         COALESCE(p.posts, 0) AS posts, COALESCE(c.clicks, 0) AS clicks
  FROM posts p FULL JOIN clicks c USING (yr, platform)
),
final AS (
  SELECT yr, platform, posts, clicks,
    ROUND(100 * SAFE_DIVIDE(posts  - LAG(posts)  OVER w, LAG(posts)  OVER w), 1) AS posts_yoy_pct,
    ROUND(100 * SAFE_DIVIDE(clicks - LAG(clicks) OVER w, LAG(clicks) OVER w), 1) AS clicks_yoy_pct
  FROM merged WINDOW w AS (PARTITION BY platform ORDER BY yr)
)
SELECT * FROM final WHERE yr BETWEEN 2022 AND 2026 ORDER BY platform, yr

See also: Rebrandly source & the parsing bug · Marketing Campaign Attribution home