Short link not tracking clicks — debugging guide
A short link not tracking clicks is almost always one of eight causes. The triage order, the diagnostic for each, and the fix for short link clicks not showing.
A short link not tracking clicks is almost always one of eight causes, and every one of them has a diagnostic that takes about thirty seconds to run. The redirect host isn't broken, your analytics view isn't broken, the standard isn't broken — something between the click happening and the click being counted is silently swallowing the event. Most posts on "short link clicks not showing" tell you to clear cache and refresh the page. That fixes nothing. This one walks the eight failure modes in the order they actually show up, with the test that tells you which one you're looking at and the fix that ends the problem. If the channel you're debugging is email specifically, half the diagnostic above gets short-circuited by the way newsletter platforms wrap your links and silently break their own attribution — worth ruling out before you suspect the redirect host.
The order matters because the cost of each fix is wildly different. A timezone misread is a one-click filter change; a broken DNS record on a custom domain is a registrar fight. A bot-filtering rule that's too aggressive is a settings tweak; a click that never reached your domain is an entire campaign that needs reshipping. Walk this list top to bottom and you'll usually land the cause inside three checks.
A short link not tracking clicks is almost always one of eight things
The eight, ranked by how often they show up in real support threads:
- The visitor never reached your domain.
- The redirect fired, but a filter dropped the event before it was counted.
- UTM parameters got stripped between the share and the click.
- The destination page consumed the click but didn't pass the signal on.
- Your dashboard is showing the wrong day.
- The custom domain is still pending TLS or DNS hasn't propagated.
- Link-preview crawlers fetched the URL before the human ever saw it.
- The slug got attached to the wrong domain in the share.
Each has a clean test. Half of them are settings problems; half are physical-world problems on the share side. Get the diagnostic right and the fix is usually less than five minutes. Reproducing the bug starts cheap: create a fresh slug in the free redirect builder, click it from your phone, and watch whether the dashboard count moves at all.
The first triage question is the cheapest one to answer: did the redirect host log a hit at all? If yes, your problem lives inside the host's filtering, your dashboard view, or the destination handoff. If no, the click never made it that far and your problem is on the share side. Most short link platforms expose a raw event log somewhere, even if the analytics surface is filtered. Find that, and you've cut the search space in half before you've done anything else. One specific wrinkle worth pulling out before you start: if the link is gated, "tracking" usually means counting the post-gate redirect, not the prompt-page view — the url shortener with password protection breakdown covers which event most platforms log on a gated link and which they quietly drop.
Cause 1 — The visitor never reached your domain
This is the most common cause and the one nobody admits to checking, because it sounds too obvious. The click didn't fail; it never happened. The link as it appears to the recipient isn't reaching your redirect host at all.
The classic version is copy-paste truncation. Someone pasted linked.codes/p/spring-launch into a chat, the chat client wrapped the line at 28 characters, and the visible URL is now linked.codes/p/spring- with the rest hidden behind a soft wrap. Some clients turn the visible portion into the actual hyperlink. The recipient clicks, hits a 404, and never lands on your redirect. Your dashboard correctly shows zero — there was nothing to log.
The second version is the link-of-a-link problem. Email platforms like Mailchimp, Constant Contact, and HubSpot wrap every URL in their own click-tracking redirect by default. So linked.codes/p/foo becomes mailchimp-track.com/abc123 which then redirects to linked.codes/p/foo which then redirects to your destination. If the email platform's tracker is broken, throttled, or being blocked by the recipient's mail client, your short link never gets the hop. The email platform reports the click; your platform reports zero. Both are technically correct.
The third version is paste-as-plaintext into apps that don't autolink. LinkedIn comments, certain forum platforms, some Slack channels with link-detection disabled — the link renders as text and recipients have to copy-paste it themselves. A meaningful fraction won't bother, and the ones who do will sometimes fat-finger a character.
The diagnostic for all three is the same: paste the actual rendered link from the actual share surface (the email as the recipient sees it, the social post as it renders) and check whether the URL that gets executed on click matches the URL you intended. If it doesn't, you're never going to see those clicks, no matter what your dashboard's filters look like. The fix depends on the variant: turn off the email platform's wrapper (or accept that its numbers are the source of truth), shorten the URL further so wrapping doesn't bite, or move to a branded short link on a domain you control so the recipient sees something obviously trustworthy and copy-pasteable.
Cause 2 — The redirect fired, but a filter dropped the event
Now you've confirmed (via the raw event log, or by clicking the link yourself from a phone on cell data) that the redirect host did receive the request. But your dashboard still shows zero. This is the second-most-common cause: an event-counting filter is too aggressive.
Three filters typically run on every short-link platform between raw event and counted click:
- Bot/crawler filter. Drops requests from known automated user agents — search engine spiders, link-preview fetchers, uptime monitors. Some platforms also drop "suspected bot" traffic based on heuristics, which can occasionally misfire on real mobile browsers with unusual user-agent strings.
- IP allowlist or blocklist. Some accounts have an "exclude my office IP" rule set up so internal testing doesn't pollute campaign numbers. If everyone clicking from your team is being filtered out and that's your test pool, you'll see zero.
- Dedup window. A click within N seconds of the same IP/user-agent combination clicking the same slug is treated as a refresh, not a new click. Default windows are usually 5 to 30 seconds. If you're refreshing the destination to test, you're not generating new counted clicks.
The diagnostic is to pull the raw event log alongside the counted-click number. If raw events outnumber counted clicks substantially, one of these filters is doing the dropping. The fix is to inspect each filter setting, widen it if it's swallowing real traffic, and re-test from a clean network. Linked.Codes exposes the bot filter on the project settings page and the dedup window in the analytics tab; for other platforms, dig through the help docs for "filter," "exclude," and "dedup."
The single subtlest version of this cause is the dedup window mis-set on a high-traffic page. If the same article is being shared in a corporate Slack and 30 employees click within the same 30 seconds, a 60-second dedup window collapses all of them to one or two counted clicks. The fix is to drop the window to something like 5 seconds for that link, or turn dedup off entirely if you're confident your raw traffic is mostly clean.
Cause 3 — UTM parameters got stripped en route
This one looks like the link tracked fine but your campaign attribution is broken — clicks show up, but they all land on (direct) or (none) in your downstream analytics. The redirect logged the hit; the destination's analytics has no idea where those visitors came from.
The cause is UTM stripping. A handful of places do this:
- iOS Mail and Outlook on iOS sometimes strip query parameters when forwarding messages or when the recipient long-presses to copy a link. The shared link arrives parameter-free.
- Some chat apps strip on paste. Telegram, Signal, and certain Slack workspace settings have URL-cleanup rules that drop tracking parameters as a privacy feature.
- Browser extensions like uBlock Origin, Brave's built-in shield, and AdGuard remove utm_* parameters by default for many users on click.
- Server-side aggressive cleanup. Some link shortener middlemen (cause 1's mailchimp-track problem) reconstruct the destination URL without preserving the query string, especially if they don't recognise it.
The diagnostic is to compare the redirect log (which sees the URL exactly as the click arrived) with the destination analytics (which sees what the browser actually sent on landing). If your redirect host is logging ?utm_source=newsletter but Google Analytics is reporting all those visits as (direct), the parameters are getting dropped between the redirect and the page view. The fix is to push the campaign attribution onto the redirect server itself — record utm_source at the redirect log, and stop relying on the destination to see it. We unpack the full UTM-tagging pattern in the UTM parameters for short links post, including the naming conventions that survive multi-hop forwarding.
A counterintuitive fix worth flagging: if you can, encode the campaign info in the slug instead of the query string. linked.codes/p/spring-launch-newsletter is a more durable signal than linked.codes/p/spring-launch?utm_source=newsletter, because nothing strips a path. The cost is one slug per campaign-source pair instead of one slug shared across sources, but the data is bulletproof.
Cause 4 — The destination consumed the click but didn't pass it on
This is the inverse of cause 3. The redirect logged it cleanly, the UTM parameters survived, and the destination page received the visit — but the destination's own analytics is showing nothing. The click made it; the page-view tracking is missing.
Two patterns:
- The destination doesn't have analytics installed. Sounds dumb, happens constantly. The redirect tracked the click, the page loaded, but there's no Plausible/GA snippet on that specific landing page (someone deployed without it, or the snippet's broken on a particular template). The redirect is your only record.
- Ad-blockers stripped the analytics request. Privacy-focused browsers and extensions block requests to common analytics endpoints. The page loads, the user is real, but the page-view event never fires because the script that fires it is being blocked.
The diagnostic is to load the destination URL in a clean incognito browser with all extensions disabled, watch the network panel, and check whether your analytics endpoint receives the request. If it doesn't fire even in a clean browser, your snippet's broken or missing. If it fires in clean and not in your usual browser, ad-block is the culprit and the gap between redirect-host clicks and destination page-views is privacy software, not tracking failure.
The pragmatic frame is to treat your redirect-host clicks as the truer number. They sit at the edge — every request that touches your redirect gets logged, regardless of what extensions or scripts the user runs after. Page-view counts have a structural undercount baked in by ad-block prevalence (around 25% to 40% on tech-savvy audiences, lower on broad consumer traffic). If you need actual attribution, tracking on the redirect layer instead of the destination is the more honest pattern.
Cause 5 — Your dashboard is showing the wrong day
The smallest and most embarrassing cause. The clicks are tracked. The data is there. You're looking at the wrong window.
Two flavours:
- Timezone mismatch. The dashboard renders in UTC; the click came in at 11pm local time, which is 4am UTC the next day. You're filtered to "today" and "today" doesn't include the click. Or the inverse — the click came in this morning local time but the dashboard's "yesterday" filter still includes it from a UTC perspective.
- Quick filter still applied. You filtered to "last 7 days" or "this campaign" three sessions ago, navigated away, came back, and the filter persisted. The view is correct for that filter. The click you're looking for is outside it.
The diagnostic takes about ten seconds: change the filter to "all time" and look for the click. If it's there, you had a filter problem. If it's not, move on. The fix is to check what timezone your dashboard renders in, what timezone you're testing from, and reconcile the two before you start chasing harder causes.
This bites every single team that deploys analytics. It's not a weakness; it's an information-architecture flaw that nearly every dashboard inherits because UTC is server-default and the user is local.
Linked.Codes shows clicks in your local timezone with raw event logs one click away — bot filter and dedup are settings you can audit, not a black box.
Try it freeCause 6 — The custom domain hasn't propagated yet
If you just set up a custom domain (like go.yourbrand.com pointing at your short-link host) and the link tracks zero, the most likely cause is that DNS or TLS hasn't finished settling. Two specific conditions:
- DNS propagation lag. A new CNAME or A record can take from minutes to 48 hours to propagate globally. Your laptop on a fast ISP sees the new record immediately; the recipient on a corporate network with aggressive DNS caching might be looking at the old
NXDOMAIN(or worse, the domain registrar's parking page) for hours after. - TLS certificate not yet issued. Modern short-link hosts use Let's Encrypt or similar automatic certificate authorities, which issue a TLS cert only after the domain's DNS resolves to the right host. There's a window — sometimes minutes, sometimes hours — between DNS being correct and the cert being live. During that window, browsers will show a security warning and most users will bail before the redirect fires.
The diagnostic uses a public DNS checker (whatsmydns.net or dnschecker.org) to see what your CNAME resolves to from multiple geographic locations. If most regions show the right answer, propagation is fine. If half the world still sees the old record, you have to wait. For TLS, hit https://yourdomain.com/.well-known/acme-challenge/test (any path will do) — if you see a cert error, the issuance hasn't completed.
The fix is patience plus communication. Don't ship the campaign on a custom domain that went live in the last 24 hours. If you must, the safer pattern is to share the platform's default domain (linked.codes/p/foo) for the first 24-48 hours and swap in the branded domain once you've confirmed propagation is complete. Because dynamic redirects are content-addressable by slug, both URLs point at the same destination — only the surface changes.
Cause 7 — Link previews fired the redirect, not the human
Slack, Telegram, Apple iMessage, Discord, WhatsApp, LinkedIn, Twitter, Facebook Messenger — every modern messaging app fetches every URL it sees in a message to build the inline preview card. Those fetches hit your redirect host before any human ever clicks. If your bot filter is too lax, those preview fetches show up as counted clicks. If your bot filter is too aggressive, real humans on certain user-agents get filtered out alongside the previews.
The patterns to recognise:
- Inflated counts immediately after a share. You posted a link in a 50-person Slack and 50 "clicks" registered in the first three seconds. Those are 50 Slack preview-fetches, not 50 humans. The real click count usually arrives over the following minutes and hours.
- A spike with zero downstream activity. 200 clicks logged, zero page-views on the destination, zero conversions, zero engagement. Almost certainly an automated scanner or preview crawler hitting your redirect.
- The reverse — filter too aggressive — drops real clicks. Some link-preview crawlers identify themselves with user-agents that overlap with real mobile browsers. An over-eager bot filter that drops anything matching "bot" or "spider" can occasionally chew on real Android clients with debug-flavoured user-agents.
The diagnostic is to compare your redirect-host click curve with your destination-page page-view curve over the same time window. If clicks spike and pageviews don't, the spike is automated. If clicks are far below pageviews (which is unusual but possible), filtering's too aggressive and you're under-counting.
The fix is to use a curated bot-filter list rather than a heuristic, and to trust your real-time numbers less for the first hour after a share. We touched on the same problem in the dynamic QR types post — preview crawlers hit QR-encoded URLs the same way they hit pasted URLs, and the same filter logic applies. The same curated bot-list also drives device-targeted short links, where serving Googlebot the iOS App Store URL is the SEO-killing version of the same misclassification.
Debug checklist — what's the cause of zero clicks?
The checklist persists what you've ticked across page reloads, so you can leave it half-done while you actually run the diagnostics, then come back and pick up where you left off. The verdict narrows as you confirm each item — the order matches the diagnostic priority above.
Cause 8 — Wrong slug on the wrong domain
This is the runner-up to cause 1 in the "embarrassingly common" stakes. You created spring-launch on go.brand-a.com but the campaign manager pasted go.brand-b.com/spring-launch because they were thinking about the other client. The link 404s, no clicks register, you assume tracking is broken.
The diagnostic is to take the rendered URL from the actual share surface and paste it into your platform's "find slug" search. If the slug doesn't exist, the URL was wrong. If it exists on a different domain than the one in the share, the share has the wrong host.
The fix is process: every time a slug is created on a multi-domain account, the share copy should be generated by clicking "copy link" inside the platform UI — never typed by hand. Hand-typed short URLs get domain-confused at a depressingly steady rate. The single biggest reduction in this class of error in our own data came from making the "copy link" button the most prominent action on the slug detail page, more visible than the destination URL itself.
How long until clicks show up?
A common framing of "tracking is broken" is actually a tracking-lag misread. Most platforms count clicks in near real-time but render them on the dashboard with a small delay — usually under a minute, occasionally up to ten on heavily aggregated platforms. If you click your own link and refresh the dashboard immediately, you may see zero for thirty seconds and one a minute later. Wait two minutes before declaring tracking broken; almost half the "zero clicks" panics resolve themselves in that window.
The other lag pattern is the daily aggregate. Some platforms commit the day's data to the historical view at midnight UTC, so "today" and "yesterday" in the dashboard reflect a different cutoff than what you'd think looking at a calendar. If you're staring at "yesterday" expecting clicks from a campaign sent at 6pm local time, those clicks may still be in the "today" bucket from the dashboard's perspective until UTC rolls.
Why does my analytics show 0 clicks even though I know people clicked?
The most common cause is that real clicks are being filtered out by an over-aggressive bot rule, IP allowlist, or short dedup window. Pull the raw event log alongside the counted-click number — if raw events exist but counted clicks don't match them, a filter is dropping events. Less commonly, the dashboard is filtered to the wrong day or your timezone is different from the dashboard's.
Do link-preview bot scans count as clicks?
Most platforms try to filter them out, but the filtering is imperfect. When you share a link in Slack, Telegram, iMessage, or any modern messaging app, the app fetches the URL automatically to build a preview card. Those fetches hit your redirect host. A good bot filter drops them; an over-aggressive one also drops real mobile browsers; a permissive one inflates your numbers. The best signal is the curve — preview hits arrive in a 1-3 second burst right after the share; real clicks trickle in over hours.
How long until clicks show up after I click the link myself?
Usually under a minute. Some platforms have a 30-second to 10-minute aggregation lag before the dashboard refreshes. If you don't see your own click after 5 minutes, then start debugging — but skip this check on the first attempt because half of "zero clicks" panics resolve themselves with one cup of coffee.
Why does the click count differ between my short-link host and Google Analytics?
The redirect host counts every visit that touches it. The destination page only counts visits where the analytics script actually runs — which excludes ad-block users, quick-bouncers who close before the script loads, and bots that fetch the redirect but don't render the page. The redirect-host number is structurally higher and structurally more accurate as a click count. The destination-page number is structurally lower and more useful as an engagement signal.
Can I undo a wrong UTM tag after the campaign has shipped?
Not on existing clicks — those are baked in. But for future clicks, yes: if your short link is dynamic, you can change the destination URL to a corrected one with the right UTM, and every subsequent click will use the new tag. The clicks already in the system retain whatever you tagged them with at the time. If you really need consistent tagging, the cleanest fix is to record the campaign info at the redirect-host level (in the slug or a separate metadata field) and ignore the UTM in the destination URL entirely.
Do incognito or private browsing clicks track?
Yes — the redirect host doesn't care about your browser mode. What private browsing changes is cookie-based deduplication on the destination side; the redirect itself logs every hit regardless. If you're testing your own link, incognito is actually the safer test because it bypasses cached redirects and old session cookies that might cause weird behaviour.
If my link uses a custom domain, does that change tracking accuracy?
It can improve it. Branded domains take longer to be flagged by privacy extensions and ad-block lists than shared shortener domains, so a higher fraction of real clicks get logged. Branded domains also avoid the click-through suspicion gap — recipients click a domain they recognise more readily than they click a generic shortener, which gives you a higher true-click rate to begin with.
How Linked.Codes handles each cause
If you're already on Linked.Codes, every cause has a corresponding place to look. The raw event log lives under each slug's analytics tab — that's the unfiltered ground truth. The bot filter is in project settings; the dedup window is configurable per project, defaulting to 5 seconds. Custom-domain DNS and TLS state are surfaced on the domain detail page with explicit "DNS pending" and "TLS issuing" indicators. UTM survivability is exposed as a "destination URL with parameters preserved" log entry next to each click. Timezone is set per-account in your profile and applies everywhere the dashboard renders dates.
The principle is to keep every layer auditable. A "tracking is broken" support ticket from a customer should be answerable in under five minutes by walking the eight causes against the raw log. Keeping the data ungilded — no smoothing, no rounding, no silent filtering — is what makes that possible. The full doc walkthrough lives in the analytics documentation if you want the platform-specific path through each diagnostic. For the underlying argument about why redirect-layer tracking is more durable than destination-page tracking, the owning your link infrastructure post is the longer version of that case.
Sourcesshow citations
- RFC 9110 — HTTP Semantics (3xx redirect status codes and how counting works) — https://www.rfc-editor.org/rfc/rfc9110.html
- MDN — HTTP redirect status codes — https://developer.mozilla.org/en-US/docs/Web/HTTP/Redirections
- MDN — Referrer Policy and what gets sent on redirect — https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referrer-Policy
- Cloudflare docs — Bot management and known-good-bot lists — https://developers.cloudflare.com/bots/concepts/bot/
- Google Analytics 4 — Default channel groupings and how (direct) gets assigned — https://support.google.com/analytics/answer/9756891
- W3C — URL Living Standard (query string handling) — https://url.spec.whatwg.org/
- Let's Encrypt — Automatic certificate issuance and propagation timing — https://letsencrypt.org/docs/challenge-types/
Try it on your own domain
Branded short links and dynamic QR codes, on your subdomain or your own domain. One-time purchase, no per-click fees.