<- Back to blog
How-to9 min readUpdated May 1, 2026

How to Track Outbound Link Clicks (2026 Guide)

A practical 2026 guide to tracking outbound link clicks with privacy-friendly analytics. Copy-pasteable HTML and JavaScript, common pitfalls, and FAQs.

track outbound linksoutbound link analyticsexternal link trackingclick tracking javascriptplausible alternative outbound clicksprivacy friendly analytics events

TL;DR

  • 1.Outbound clicks are the easiest custom event to set up — one snippet, one event listener, ten lines of code.
  • 2.Use a single delegated `click` listener on `document` rather than tagging every link manually.
  • 3.Send the destination hostname (not the full URL) to keep events anonymous and useful.
  • 4.Watch for middle-click and Cmd-click — modern browsers do not fire `click` for these unless you handle `auxclick`.
  • 5.In Sleek, outbound clicks show up in the Events tab next to pageviews; you can group by destination domain.

Step 1: install the analytics snippet

If you already have Sleek installed, skip this section. Otherwise, drop the snippet into your `<head>` tag. It is around 1 KB and loads asynchronously, so it will not block your page render.

index.html
<script async src="https://getsleek.io/v1.js" data-site="YOUR_SITE_KEY"></script>
tip:Replace `YOUR_SITE_KEY` with the key shown on your Sleek dashboard. The script exposes a global `window.sleek` function that you will use to send events.

Step 2: add a delegated click listener

The cleanest way to track every outbound link is one listener on `document`. You do not need to add `onclick` attributes to every link, you do not need to wrap your `<a>` tags in a component, and you do not need to remember to tag new links when you add them. The listener fires for every click, you check whether the target is an outbound `<a>`, and you send the event.

Here is the minimum version. It handles the regular click. We will handle middle-click and right-click open-in-new-tab in step 3.

outbound.js
// Track every click on an external <a> link.
document.addEventListener('click', function (event) {
  const link = event.target.closest('a')
  if (!link || !link.href) return

  // Same-origin links are not outbound — skip them.
  if (link.hostname === window.location.hostname) return

  window.sleek('track', 'outbound_click', {
    destination: link.hostname,
    href: link.href,
    text: (link.innerText || '').slice(0, 80),
  })
})

Step 3: handle middle-click and modifier-click

Modern browsers do not always fire a `click` event when you middle-click a link or Cmd-click it to open in a new tab. They fire an `auxclick` event instead. If you stop at step 2, you will under-count by 20–40% on a content site where readers open lots of tabs.

The fix is to listen for both events. The handler stays identical — only the listener registration changes.

outbound.js
function handleOutbound(event) {
  // Ignore right-click context menu opens.
  if (event.type === 'auxclick' && event.button !== 1) return

  const link = event.target.closest('a')
  if (!link || !link.href) return
  if (link.hostname === window.location.hostname) return

  window.sleek('track', 'outbound_click', {
    destination: link.hostname,
    href: link.href,
  })
}

document.addEventListener('click', handleOutbound)
document.addEventListener('auxclick', handleOutbound)

Step 4: decide what to send (and what not to)

You have three reasonable options for what to put in the event payload: the full URL, the hostname only, or both. Privacy-friendly setups usually send just the hostname — that is enough to answer "which sites do my readers click out to" without storing every individual URL.

If you run an affiliate site and you need to know which specific link converted, send the full URL. Sleek will store it and group identical URLs together in your dashboard.

Avoid sending personal data in event properties. Email addresses, user IDs, and anything else that could identify someone do not belong in click events — they do not help you make decisions and they create compliance risk.

  • Send `destination` (hostname) for aggregate reporting — "30% of clicks go to twitter.com".
  • Send `href` (full URL) when you need per-link conversion data — affiliate tracking, doc deep links.
  • Send `text` (link text) when you have multiple links to the same destination and want to know which CTA wins.
  • Do not send query strings that contain emails, tokens, or session IDs.

Step 5: verify the events are arriving

Open your site in a regular browser tab — not an incognito window with extensions disabled. Click an outbound link. Open the Sleek dashboard in a second tab and look at the Real-time view. You should see an `outbound_click` event within a few seconds, with the destination hostname filled in.

If nothing shows up, the most common cause is an ad blocker. Sleek's script is privacy-friendly and most blockers leave it alone, but a small minority block all third-party scripts on principle. Test in a browser without extensions to isolate.

The second most common cause is a `target="_blank"` link that triggers `window.open` synchronously and tears down the page before the network request completes. Sleek's SDK uses `navigator.sendBeacon` under the hood to handle this, so it should not be an issue — but if you wrote your own tracker, this is the bug to look for.

warning:Do not call `event.preventDefault()` in your click handler. If you delay navigation to wait for the analytics request, you create a sluggish click that users will notice. The browser handles concurrent navigation and beacon sends correctly on its own.

Reading the results in your dashboard

In Sleek, outbound clicks land in the Events tab. The default grouping is by event name, so you will see `outbound_click` with a count next to it. Click into the event and you can group by any property you sent — `destination`, `href`, or `text`.

A useful first report: filter the last 30 days, group by `destination`, and sort by count. This is your "where do readers go after my site" leaderboard. For a content site that is often the most actionable view in the entire dashboard.

A second useful report: filter to a single high-traffic post (set the page filter), then group by `destination`. Now you know which post is driving traffic to which external site. If you have affiliate links, this is your conversion attribution.

Common pitfalls

None of these are showstoppers, but each one quietly degrades the data quality. The setup above avoids all five.

  • Forgetting `auxclick` — under-counts middle-click and Cmd-click opens.
  • Tagging links manually with `onclick` instead of using delegation — breaks every time someone adds a new link.
  • Sending the full URL when the hostname would do — clutters your dashboard and slightly hurts privacy.
  • Stopping the navigation with `preventDefault` — creates a perceptible click delay.
  • Not testing with a real ad blocker — your team's clicks are tracked but a portion of real-world clicks are not.

Frequently asked questions

Do I need a cookie consent banner to track outbound clicks?

Not with Sleek. Outbound click tracking is anonymous — we send the destination hostname, not anything about the visitor. There are no cookies set and no personal data collected, so under GDPR and ePrivacy you do not need a consent banner. If you are using Google Analytics, the answer is different: GA4 sets cookies, so consent is required in the EU.

How do I track only specific outbound links instead of all of them?

Add a CSS class or data attribute to the links you care about, then check for it in the listener. For example, if you tag affiliate links with `class="affiliate"`, your handler can do `if (!link.classList.contains("affiliate")) return` before sending. This is also a good pattern when you want to avoid double-tracking links that already have other instrumentation.

Why is my outbound click count lower than my UTM click count from another platform?

Two reasons. First, ad blockers block analytics scripts more aggressively than they block UTM redirects, so analytics will under-count by 5–15%. Second, bots and crawlers often follow links but do not run JavaScript, so they show up in server-side click counts but not in your analytics. Your analytics number is closer to real human clicks.

Can I track outbound links inside a Single Page Application?

Yes. The delegated listener on `document` works the same way regardless of whether your app is a SPA. Just make sure the script tag loads on the initial page render — once the listener is attached, it survives all client-side route changes.

Should I track clicks on `mailto:` and `tel:` links too?

Often yes — especially on contact pages. Add a second branch in the handler: if `link.protocol === "mailto:"` send a `mail_click` event; if `tel:` send a `phone_click`. These are usually high-intent actions worth their own event name.

How do I avoid tracking my own clicks during development?

Add a query parameter or hostname check at the top of the script. The simplest version: `if (window.location.hostname === "localhost") return` before any tracking call. Sleek also has an "exclude my IP" option in the dashboard if you prefer.

Is there a no-code way to do this without JavaScript?

Sleek has automatic outbound click tracking that you can toggle on in the dashboard — no event listener required. The manual setup in this guide is for teams that want to customize the event properties (e.g., to add the link text or a campaign tag).

Track your own growth loop

Sleek Analytics gives you visitors, sources, pages, devices, and real-time behavior with one lightweight script. No cookies, no GDPR banners.

Related reading