Skip to main content
Social mediaBy SendURL team18 min read

Instagram Link Tracking: Bio, Stories, DMs, Ads and QR

Part of the Social media handbook

Track every Instagram link: five bio slots, Story stickers, DMs, ads, creators and print. Plus how to target an Instagram campaign, when to post, why GA4 calls Instagram traffic Direct, and a campaign checklist.

Instagram never tells you who clicked your link. What you can get is a count per placement (each bio link, each Story, each DM reply, each creator) with the time, country and device behind every click. Instagram link tracking that works gives every placement its own short link, set up before you post, with UTM parameters on the destination if you use Google Analytics.

This guide is the Instagram part of the social media link tracking handbook. It covers where Instagram lets you link, the tracking setup for each placement, how to target and time a campaign, and how to read the clicks. Stories have their own guide: tracking Instagram Story link sticker clicks.

What Instagram shows you, and what it doesn't

Instagram's insights are free for professional (creator and business) accounts; switching a public account to professional costs nothing. For links, the useful parts are:

InsightWhat it countsWhere
Story InteractionsReplies, shares, sticker taps and link tapsOpen the Story, then Activity > Insights
Story Profile activityProfile visits, follows and website clicks from the StorySame screen
Account Total followersTop locations, age range and the times followers are most active (from 100 followers)Insights from your profile

What insights don't give you:

  • Who tapped. No names, no list of accounts.
  • What happened next. A tap is counted inside the app. Whether the page loaded, and whether anyone bought, happens outside it.
  • A per-link split of your bio. Instagram's help pages don't describe one for the five bio links, and we couldn't confirm one in the app.
  • DMs, creators' posts and print. A link you paste into a DM, a link a creator posts, and a QR code on a poster are invisible to your insights.

A short link per placement fills those gaps. It counts each click when it reaches snu.to, so it measures arrivals rather than taps, and it works wherever the link is posted. It doesn't identify anyone either: SendURL records country, never city, and no account details.

PlacementClickable?Tracking setup
BioYes, up to 5 links (Help Centre)One short link per slot
StoryYes, link sticker, all accounts since 27 Oct 2021 except new accounts and repeat rule-breakers (Instagram)One short link per Story frame
HighlightsYes, the Story's sticker goes with it; Highlights stay on your profile "until you remove them" (Instagram)Same link as the Story; consider an expiry
Direct messagesYes, opens in the in-app browser (Help Centre)One link for DM replies
Feed post and Reel captionsNo, on most accountsMeta One Advanced, from $49.99 a month, lists "links in organic posts and reels" (Meta, 15 Sep 2026)
Reels product linksCatalogue products only: up to 30 per Reel, in the countries Meta lists (Instagram, 24 Mar 2026)Meta's shopping reports, not a short link
AdsYes, the action buttonTagged destination URL, no short link (see ads)
PrintThrough a QR codeOne short link per printed piece

Two consequences. First, "link in bio" now means up to five links, so you can give a campaign its own slot without losing your evergreen link. Second, posting a short link in a caption does almost nothing: it isn't tappable, and the post should point to the bio or a Story instead.

All of these point at the same destination, https://example.com/autumn-sale, tagged differently:

PlacementSlugutm_contentWhat you learn
Bio slot 1 (evergreen shop link)shop-ig-bio1bio-link-1Baseline traffic from the profile
Bio slot 2 (campaign)autumn26-ig-bio2bio-link-2Whether the campaign moved profile visitors
Story, 14 Oct, frame Aautumn26-st-1014astory-1014-aClicks per Story frame, by hour
DM repliesautumn26-ig-dmdm-replyHow many people you answered actually went
Creator Mayaautumn26-cr-mayacreator-mayaEach creator's clicks without asking for screenshots
Creator Leoautumn26-cr-leocreator-leoSame, for comparison
Shop window posterautumn26-posterwindowScans of the printed QR code

Create them in the SendURL console (the form proposes a random 6-character slug, or you type your own), or from a sheet with the script in the social media hub. Slugs are case-sensitive, unique across snu.to and permanent, so use the campaign prefix and lowercase. How to name a custom short link has the rules.

The bio slot needs one more decision. If slot 2 rotates from campaign to campaign, either replace the link in Instagram with the new campaign's short link (clean history per campaign), or keep one short link in the slot and change where it points. SendURL changes a destination through the API only (PATCH /links/:id with a new destinationUrl), and the click history then spans every campaign the link served.

Posting the same video as a Reel and on TikTok? Give each profile its own link. On TikTok there is one bio link and no per-video count; how to track TikTok bio link clicks matches click times to posts to estimate which video sent them.

UTM parameters for Instagram

If you use GA4, tag every destination. These values land where you expect under Google's default channel rules, checked 15 October 2026:

Placementutm_sourceutm_mediumutm_contentGA4 channel
Bioinstagramsocialbio-link-2Organic Social
Storyinstagramsocialstory-1014-aOrganic Social
DMinstagramsocialdm-replyOrganic Social
Creator postinstagramsocialcreator-mayaOrganic Social
Ads{{site_source_name}}paid-social{{ad.name}}Paid Social

utm_campaign is the same everywhere, for example 2026-10-autumn-sale. Values that cause trouble:

  • utm_source=insta, ig_bio or instagram_story: not on Google's social source list. With utm_medium=social the visit still lands in Organic Social; with a made-up medium such as story or bio, it lands in Unassigned.
  • Instagram and instagram in different links: GA4's channel rules ignore case, but its reports don't, so you get two rows (Google).
  • UTMs on the short link: snu.to/autumn26-ig-bio2?utm_source=instagram doesn't work, because SendURL doesn't pass on a query added to the short URL. Tag the destination, then shorten it.

A tagged destination looks like this:

Destination behind snu.to/autumn26-ig-bio2Text
https://example.com/autumn-sale?utm_source=instagram&utm_medium=social&utm_campaign=2026-10-autumn-sale&utm_content=bio-link-2

Why Instagram traffic shows as Direct in GA4

Instagram opens links in its in-app browser by default, "when you tap a link in a post, ad, Story or message" (Help Centre). Outbound links pass through Meta's link shim, which exists to tell the destination the visit came from Meta while hiding the address of the page it came from (Meta Engineering, 2012). When a referrer survives, it is usually the shim's host, l.instagram.com, which is on Google's social source list, and the visit counts as Organic Social. When no referrer arrives, GA4 has nothing to go on and files the session as Direct.

UTMs settle it, because they travel in the URL rather than in a header. For the clicks themselves, the short link doesn't need a referrer: each placement has its own link. SendURL also records the app when it identifies itself, so a click opened inside Instagram shows browser: "Instagram" with browserType: "inapp" in its click record. A click on your bio link that opened in Chrome or Safari came from Instagram on the web, or from a copy of the link shared somewhere else.

Target an Instagram campaign

Targeting starts with who clicks, not who follows. Three sources, from free to paid:

1. Instagram's own audience insights. The account's Total followers insight shows top locations, age range and the times followers are most active, once you have 100 followers. That is who could see an organic post.

2. Your click data. After the first week, compare the country and device of the clicks on each placement. Followers are where your audience lives; clicks are where your buyers are likely to be. For example, if a creator's link draws most of its clicks from one country you don't ship to, that creator is reaching the wrong market, however big their audience. SendURL gives country from the IP address (no city, and VPNs move it), so treat it as a strong hint rather than an address.

3. Paid targeting in Meta Ads Manager. Meta's Advantage+ audience lets Meta's AI find the audience instead of you defining it. You can still set audience controls, which are hard limits: locations, minimum age, custom audiences to exclude, and languages. Age, gender, detailed targeting and custom audiences can be added as suggestions, which Meta may go beyond "when it's likely to improve performance" (Meta Business Help Centre). A custom audience can be built from people who engaged with your Instagram account (Meta for Developers).

A practical order: post organically first, read a week of clicks by country, then set the ad's location controls to the countries where clicks came from and use the engaged-audience custom audience as a suggestion. Meta doesn't recommend Advantage+ audience for retargeting, so retarget with a regular audience.

For Instagram ads, put the full tagged destination in the ad's website URL, not a snu.to link. Two reasons:

  • Meta adds to the URL. Dynamic parameters such as {{campaign.name}} and {{placement}} are filled in at click time, and Meta attaches its click ID, fbclid, to the URL "when a user clicks an ad on Facebook and/or Instagram" (Meta for Developers). On a short link, SendURL would drop all of it, because it doesn't pass on a query added to the short URL. Your site, its pixel and GA4 would lose them.
  • Ads Manager counts the clicks already. A short link would duplicate a number you have, and lose the parameters above.

Meta's parameter list includes {{campaign.name}}, {{adset.name}}, {{ad.name}}, {{placement}} (for example instagram_feed, instagram_stories) and {{site_source_name}}, which is ig for Instagram and fb for Facebook (Meta Business Help Centre). In the ad's URL parameters field:

Ad URL parameters (Ads Manager)Text
utm_source={{site_source_name}}&utm_medium=paid-social&utm_campaign=2026-10-autumn-sale&utm_content={{ad.name}}&placement={{placement}}

ig and fb are both on Google's social list, so with paid-social these visits land in Paid Social. Messenger (msg) and Audience Network (an) are not on the list and would land in Paid Other. Name-based parameters keep the name the ad had when it was first published, so name ads in lowercase with hyphens before you publish. A typed utm_campaign (as above) avoids the spaces a campaign name brings (%20 in the URL).

Use a short link in an ad only where people will type or scan it: a URL shown in the video, or a QR code in the creative.

When to post: what the studies measure

Every published "best time to post on Instagram" study measures engagement (likes, comments, shares, saves), and they don't agree:

StudyPublishedDataMetricInstagram answer
Sprout Social31 Mar 2026~2 billion engagements, ~307,000 profiles, 27 Nov 2025 to 27 Feb 2026Engagements including clicks, local timeMon 2 to 4pm, Tue 1 to 7pm, Wed 12 to 9pm, Thu 12 to 2pm
BufferSep 20269.6 million Instagram posts, Jan 2024 to Dec 2025Median engagement rateThu 9am, Wed 12pm, Wed 6pm
Hootsuite19 Nov 20251 million+ posts across networksEngagement, "time-zone agnostic"Mon 3 to 9pm, Tue 5 to 8am and 3 to 7pm, Thu 5 to 7pm
Later21 Apr 20266 million+ feed posts, Jan to Oct 2024Engagement rate, audience local time5am

Sprout's engagement count includes link clicks among reactions, comments, shares and messages; none of the four reports link clicks on their own. A like and a click are different decisions, made at different moments, so treat these windows as a starting point for a test, not an answer.

Your own data is better on both counts. Instagram's Total followers insight shows when your followers are active. Your short links show when people actually click, and how long each placement keeps earning: a Story's clicks come in a burst and stop when it expires after 24 hours, while a bio link collects for weeks. Post the same kind of Story at two different times, each with its own link, and compare clicks in the first 24 hours. Find your best time to post from link clicks builds a weekday-by-hour heatmap from the timestamps.

Track a campaign end to end

A plan for a two-week Instagram campaign, from setup to read-out:

  1. A week before. List every placement in the tracking sheet: bio slot, each planned Story, DM replies, each creator, each ad, each printed piece. Decide the reading day.
  2. Create the links. One per row, tagged destination, campaign-prefixed slug. Add an expiry to links for an offer that ends; a Story in Highlights keeps its link working after the sale is over.
  3. Brief the creators. Send each one their own short link, snu.to/autumn26-cr-maya, for their Story sticker or bio. You'll see their clicks without access to their account or screenshots of their insights. A creator-specific promo code is a useful cross-check: clicks show interest, codes show sales.
  4. Set up the ads with the tagged URL and Meta's dynamic parameters, as above.
  5. Print. Each printed piece gets its own link's QR code (SVG from the console). Scans are flagged source: "qr", so the poster stays separate from everything else. A QR code can also point a short link at your Instagram profile, which counts how many people the poster sent to Instagram.
  6. Launch day. Open each short link once on a phone to check it lands; note that each test is a click.
  7. Read on the chosen day. Clicks per placement per day live, previews discounted, device and country per placement, GA4 sessions by utm_content.
  8. Act. Keep the placements that earned clicks, drop or change the rest, and move the ad's location controls toward the countries where clicks came from.

SendURL sees the click, not the sale. Revenue per placement needs your shop's or GA4's conversion data, joined on utm_content or the promo code.

Reading the clicks

The console's link page shows total clicks, the last 7 days and a daily chart, and each click in the Recent clicks list opens its full record. For the shape of a placement over its first two days, this script buckets one link's clicks by hours since posting and shows which app they opened in. It needs the link's id (also in its console address, console.sendurl.to/links/<id>) and the time you posted (install requests first with pip install requests):

clicks_after_posting.pyPython
import os, time
from collections import Counter
from datetime import datetime

import requests

API = "https://api.sendurl.to/api/v1"
HEADERS = {"Authorization": f"Bearer {os.environ['SENDURL_API_KEY']}"}
POSTED = datetime.fromisoformat(os.environ["POSTED_AT"].replace("Z", "+00:00"))

def clicks(link_id):
    """Every click of one link, newest first, 10 per request."""
    params = {"limit": 10}
    while True:
        r = requests.get(f"{API}/links/{link_id}/clicks", headers=HEADERS, params=params, timeout=10)
        r.raise_for_status()
        page = r.json()
        yield from page["clicks"]
        if not page["pagination"]["hasMore"]:
            return
        params["cursor"] = page["pagination"]["nextCursor"]
        time.sleep(0.25)  # stay under the API's rate limit

by_hour, apps, previews = Counter(), Counter(), 0
for c in clicks(os.environ["LINK_ID"]):
    if "facebookexternalhit" in (c["userAgent"] or ""):
        previews += 1  # Meta's preview fetcher, not a person
        continue
    at = datetime.fromisoformat(c["clickedAt"].replace("Z", "+00:00"))
    by_hour[max(-1, min(int((at - POSTED).total_seconds() // 3600), 48))] += 1
    apps[c["browser"] if c["browserType"] == "inapp" else "other browser"] += 1

for hour in sorted(by_hour):
    label = "before" if hour < 0 else "48h+" if hour == 48 else f"{hour}h"
    print(f"{label:>6}  {'#' * by_hour[hour]} {by_hour[hour]}")
print("opened in:", dict(apps), "| previews skipped:", previews)

Run it with LINK_ID=<id> POSTED_AT=2026-10-14T17:30:00Z python3 clicks_after_posting.py. Clicks "before" posting are your own tests. Run it for two Stories posted at different times and you have the timing test above; run it for each creator and you see whose audience clicks fast and whose keeps clicking.

Free lists 7 days of analytics history and Pro 30; the link page and the API cover every click. What a click record contains explains each field, and can you see who clicked your link covers what the data can't tell you.

Checklist

  • Bio: a campaign slot (of five) with its own short link; the evergreen link left in slot 1
  • One short link per Story frame, DM reply, creator and printed piece, all with the campaign prefix
  • Destinations tagged utm_source=instagram&utm_medium=social, utm_content naming the placement
  • Ads: the tagged URL with Meta's dynamic parameters, no short link
  • No short links in captions, where they aren't clickable
  • Expiry set on offer links that may live on in Highlights
  • Location and device of first-week clicks checked before ad targeting is set
  • Posting times noted for each Story and post, so clicks can be read by hours since posting
  • Reading day fixed; previews (facebookexternalhit) and your own test clicks discounted

Naming template for the sheet:

Instagram naming templateText
slug:         <campaign>-ig-bio<slot> | <campaign>-st-<mmdd><frame> | <campaign>-ig-dm | <campaign>-cr-<handle> | <campaign>-poster
utm_source:   instagram            (ads: {{site_source_name}})
utm_medium:   social               (ads: paid-social)
utm_campaign: <yyyy>-<mm>-<offer>  e.g. 2026-10-autumn-sale
utm_content:  bio-link-<slot> | story-<mmdd>-<frame> | dm-reply | creator-<handle> | window

Start with the bio link: shorten it on the SendURL home page and watch the first clicks arrive.

Frequently asked questions

Can you see who clicked your Instagram link?

No. Instagram's insights count link taps without naming anyone, and a link tracker sees the request, not the person. What you can see is how many clicks each link got, when, and the country, device and app behind each one.

How do I see link clicks on Instagram?

Open the Story's insights: link taps are counted under Interactions, and website clicks under Profile activity. Insights are free on professional (creator and business) accounts. For clicks that reached your site, per bio slot, DM or creator, use a separate short link in each place and read its click count.

Why does Instagram traffic show as direct in Google Analytics?

Links open in Instagram's in-app browser, and the visit often arrives without a referrer. With nothing to go on, GA4 files the session as Direct. Add utm_source=instagram and utm_medium=social to the destination URL and the visit lands in Organic Social.

How many links can you have in your Instagram bio?

Up to five. Add them under Edit profile, then Links, then Add external link. Instagram's Help Centre says anyone, on or off Instagram, can see them.

Can you put a link in an Instagram caption?

You can type one, but on most accounts it isn't clickable. Meta's paid Meta One Advanced plan, announced in September 2026, lists links in organic posts and Reels among its features, with availability varying by region and account.

Start tracking links free.

Create your first short link with click analytics in seconds. No credit card, no sign-up to start.

Shorten a link