2026-06-08 clicks (rebrandly) attribution issues
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
| Year | Symptom on dashboard | Root cause | Layer |
|---|---|---|---|
| 2024 | YouTube clicks 145k → 16k | Not a bug: real YoY decline in YouTube creator activity; the dashboard series is YouTube-only (clicks are correctly attributed — see funnel below) | clicks |
| 2025 | Installs 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.
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 year | Clicks | Parser only | + slug→sheet fallback | Production (attributed) | Still unattributed | % parser → % production |
|---|---|---|---|---|---|---|
| 2021 | 555,457 | 522,607 | +237 | 522,844 | 32,613 | 94.1% → 94.1% |
| 2022 | 623,655 | 525,676 | +87,939 | 613,615 | 10,040 | 84.3% → 98.4% |
| 2023 | 216,213 | 214,194 | +218 | 214,412 | 1,801 | 99.1% → 99.2% |
| 2024 | 69,283 | 26,726 | +32,778 | 59,504 | 9,779 | 38.6% → 85.9% |
| 2025 | 231,911 | 57,313 | +10,631 | 67,944 | 163,967 | 24.7% → 29.3% |
| 2026* | 1,080 | 325 | +719 | 1,044 | 36 | 30.1% → 96.7% |
- Parser only =
campaign_utm_ct(URL parse) alone · + slug→sheet fallback = clicks the slug→creators-sheet join adds · Production = both (whatcampaigns_funnel_clicksattributes today). - 2024 is the proof the fallback works: the parser alone gets 38.6%, but production reaches 85.9% — the OneLink campaign sits in the slug and the fallback already recovers it. Nothing to fix here.
- Still unattributed = neither parser nor sheet: mostly generic non-creator links, plus a few real creator links missing from the sheet (e.g. the Eloy Casagrande artist links).
- 2025 caveat: the 164k "still unattributed" is dominated by generic non-creator links (
download-app132k,bf25-lp28k,moiseslive17k) — never creator campaigns, so 2025's low % is not lost creator data. - Extraction note: these figures use the clean last-segment slug match (the dbt-port logic); the as-deployed Dataform model uses
SPLIT[OFFSET(1)]on an un-deduped sheet join, so its 2024 figure is slightly lower (~83.7%) and fan-out-inflated. 2026* is a partial year.
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 | |
|---|---|---|
| Universe | ALL attributed clicks (every platform + generic links) | Creator-sheet campaigns, YouTube only |
| Grouped by | Link-creation year (route_created_at) | Campaign publication year (YouTube publish date) |
| Dedup | One row per first-session click | Per-campaign click de-dup inside the workbook |
| Source | derived_marketing_master.rebrandly + creators sheet | moises_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)
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
- 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.
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 here | 2024 clicks | % of raw | Dropped here · what it is |
|---|---|---|---|---|---|
| 1 | rebrandly_prep (raw) | all click events for 2024-created links | 124,652 | 100% | — (baseline) |
| 2 | rebrandly (master) | agent_type = 'human' | 94,904 | 76.1% | −29,748 · bot/robot clicks |
| 3 | campaigns_funnel_clicks (grain) | client_session_first IS TRUE | 69,286 | 55.6% | −25,618 · repeat clicks within a session (1 click/session) |
| 4 | campaigns_funnel_clicks (attribution) | COALESCE(campaign_utm_ct, creators.campaign) IS NOT NULL | 59,507 | 47.7% | −9,779 · unattributable (no URL campaign & slug not in sheet — incl. the Eloy Casagrande artist campaign ~6.4k, missing from the sheet) |
| 5 | campaigns_funnel_creators | slug matches a creators-sheet campaign | 36,513 | 29.3% | −22,994 · attributed but non-creator / generic campaigns (e.g. br_moisesapp, bf24*, download) |
| 6 | Tableau "Posts YT" | platform = 'YouTube' | 16,844 | 13.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).
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 year | YouTube | TikTok | |
|---|---|---|---|
| 2021 | 100,786 | 68 | 0 |
| 2022 | 124,005 | 165,429 | 10,626 |
| 2023 | 140,968 | 33,879 | 1,702 |
| 2024 | 16,844 | 18,149 | 0 |
| 2025 | 46,053 | 971 | 137 |
| 2026 | 815 | 213 | 0 |
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.
| Platform | Year | Posts | Posts YoY | Clicks | Clicks YoY |
|---|---|---|---|---|---|
| YouTube | 2022 | 35 | −44% | 124,005 | +23% |
| 2023 | 102 | +191% | 140,968 | +14% | |
| 2024 | 32 | −69% | 16,844 | −88% | |
| 2025 | 75 | +134% | 46,053 | +173% | |
| 2026* | 9 | −88% | 815 | −98% | |
| 2022 | 57 | — | 165,429 | — | |
| 2023 | 76 | +33% | 33,879 | −80% | |
| 2024 | 158 | +108% | 18,149 | −46% | |
| 2025 | 367 | +132% | 971 | −95% | |
| 2026* | 158 | −57% | 213 | −78% | |
| TikTok | 2022 | 28 | — | 10,626 | — |
| 2023 | 9 | −68% | 1,702 | −84% | |
| 2024 | 34 | +278% | 0 | −100% | |
| 2025 | 104 | +206% | 137 | — | |
| 2026* | 76 | −27% | 0 | −100% |
- Posts = distinct creator campaigns by content post date (the only date the creators sheet carries), including posts with no Rebrandly link. Clicks = first-session clicks by link-creation year — the same basis as the clicks table above, so the two tables agree (YouTube 2024 = 16,844 in both). For most campaigns the link is created the same year the content is posted, so the two date bases line up closely.
- The divergence: Instagram posts grew +108% then +132% (76 → 158 → 367) while its clicks fell −80% / −46% / −95% (2023→25); TikTok posts grew to 104 with essentially 0 trackable clicks. Creator effort moved to platforms Rebrandly barely tracks (link-in-bio limits; ~60 of the 158 Instagram 2024 posts carry no Rebrandly link at all).
- "—" = prior-year base too small to be meaningful (Instagram/TikTok before 2022). 2026* is a partial year.
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
- Enhanced recoverability table:
qmb jobs sql qmb_2026-06-09_12-39-41_2ce062 - 2024 by month:
qmb jobs sql qmb_2026-06-09_12-30-48_750908 - 2025 unrecoverable composition:
qmb jobs sql qmb_2026-06-09_12-30-47_6045f9
funnel reproduction: session pi-2026-06-09-tableau-funnel-numbers
- Funnel by publication year:
qmb jobs sql qmb_2026-06-09_12-40-27_fa488d
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