Skip to main content
Social mediaBy SendURL team10 min read

Track Link Clicks in WhatsApp and SMS Messages

Part of the Social media handbook

WhatsApp and text messages hide where a click came from. One short link per group, broadcast or list fixes that. Previews, SMS length, and the UTM values GA4 files right.

To track link clicks in WhatsApp, send a short link that counts every visit, and give each group, broadcast or campaign its own link. WhatsApp doesn't report who tapped a link, and clicks from chat apps usually reach your site without a referrer, so the link you sent is the only record of where a click came from. Text messages work the same way.

A tracked link records each click's time, country, device, browser, operating system, IP address and referrer (when the app sends one), never a name. This guide explains why chat traffic hides its source, how to split it with one link per group or list, what link previews do to your counts, what to watch in SMS, and the UTM values GA4 files correctly. It is part of the social media tracking handbook.

Why chat traffic looks like Direct

A browser tells a site where a visitor came from with the Referer header, which carries "the absolute or partial address from which a resource has been requested" (MDN, updated 3 December 2025). When someone taps a link in WhatsApp, Telegram or a text message, the browser opens from an app, not from a web page, so there's usually no address to send.

GA4 files a visit with no referrer and no UTM parameters as Direct (GA4 default channel group). That is why a WhatsApp campaign can show up as a mysterious bump in Direct traffic. Marketers call this dark social.

Two fixes, and you want both:

  • UTM parameters on the destination, so GA4 files the visit under the right channel.
  • A separate short link per group, broadcast or list, so you can compare them even without GA4, and count clicks on pages you don't control.

The referrer won't tell your running club group from your parents' group. Their links will.

Where you send itShort linkWhat its count tells you
WhatsApp group "Sunday runners"snu.to/oct-sale-wa-runnersTaps from that group, including forwards out of it
WhatsApp group "School parents"snu.to/oct-sale-wa-parentsSame, for the second group
WhatsApp Channel postsnu.to/oct-sale-wa-channelTaps from followers of the Channel
Telegram channelsnu.to/oct-sale-tgTaps from Telegram
SMS to customer list Asnu.to/oct-sale-sms-aTaps from that list
SMS to customer list Bsnu.to/oct-sale-sms-bSame, for list B

A click means someone with the link tapped it, not necessarily a member of the group: people forward messages. And a link sent to one person tracks that person, which is personal data in the EU; mention link tracking in your privacy notice (not legal advice). Can you see who clicked your link? covers the line between counting placements and watching people.

Slugs are unique across all of SendURL, so give yours a prefix only you would use. To create a batch from the command line (create a link in the API reference):

One tracked link per groupShell
for group in runners parents channel; do
  jq -n --arg g "$group" '{
    destinationUrl: ("https://example.com/sale/trail-shoes?utm_source=whatsapp&utm_medium=social&utm_campaign=2026-10-autumn-sale&utm_content=" + $g),
    slug: ("oct-sale-wa-" + $g),
    title: ("Autumn sale, WhatsApp " + $g)
  }' | curl -s -X POST https://api.sendurl.to/api/v1/links \
    -H "Authorization: Bearer $SENDURL_API_KEY" \
    -H "Content-Type: application/json" \
    -d @- \
    | jq -r '[.slug // .error, .shortUrl // .message] | @tsv'
done

Then compare the groups. This script lists every link whose slug starts with a prefix, with its total clicks (install requests first with pip install requests):

clicks_by_group.pyPython
import os, sys, time

import requests

API = "https://api.sendurl.to/api/v1"
HEADERS = {"Authorization": f"Bearer {os.environ['SENDURL_API_KEY']}"}
PREFIX = sys.argv[1]  # e.g. oct-sale-

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

rows = sorted(((l["totalClicks"], l["slug"]) for l in links() if l["slug"].startswith(PREFIX)), reverse=True)
for clicks, slug in rows:
    print(f"{clicks:6}  snu.to/{slug}")
print(f"{sum(c for c, _ in rows):6}  total")

Run it as python3 clicks_by_group.py oct-sale-. The totals include previews and any other automated visits, which the next section deals with. To see one group's daily clicks without code, open its link's page in the console; that's the free link tracker every link comes with.

When you paste a link into a chat, the app fetches the page to draw a preview card. On a short link, that fetch follows the redirect and counts as a click. SendURL doesn't filter bots or count unique visitors, so you'll see these.

Where the fetch comes from matters:

  • WhatsApp and Apple Messages build the preview on the sender's phone, then send it along with the message, according to a 2020 study of link previews by the researchers Talal Haj Bakry and Tommy Mysk. So a message to a group of 200 adds one preview click, from you, not 200. Apple's own note confirms that Messages previews follow server-side redirects (TN3156).
  • The user agent is commonly reported as starting with WhatsApp/, but WhatsApp doesn't document it, so don't rely on the name alone.
  • Other apps vary. The same study found several apps fetching previews on their own servers. Telegram wasn't covered; check your first minute of clicks after a send to see what it does.
  • Text messages are the opposite case. A plain SMS carries only text, so a preview can't travel with it: if the recipient's messaging app draws one, it has to fetch the link itself, on the recipient's side, when the message arrives or is opened. That is up to one preview click per recipient, spread over the delivery time. Neither Apple nor Google documents this for SMS, so read the first clicks after a send rather than assuming one preview click in total.

The tell is timing: a click within seconds of you pasting the link, from your own country and with a non-browser user agent, before anyone could have read the message. Note when you sent each message and drop clicks in the first minute, or use the script in bot clicks and link previews, which flags them by user agent, by missing browser and by time since sending.

To see the card a link will get before you send it, paste it into the link preview checker. It follows the short link's redirect the way the apps do, so on a SendURL link the check itself adds one click.

SMS: length, encoding and trust

Length. A standard text holds 160 characters; a longer one is split into parts of 153 characters each. One emoji or other character outside the basic GSM-7 set switches the whole message to UCS-2, which holds 70 characters, or 67 per part (Twilio, updated 16 September 2026). Twilio, for one, "bills SMS per message segment sent", so through a provider the link's length is money. Sent from your own phone, length still decides whether the text splits into parts:

Same text sent from your own phone, two linksText
Acme Running: 30% off all trail shoes until Sun 19 Oct. https://snu.to/oct-sale-sms-a
→ 85 characters, 1 part

Acme Running: 30% off all trail shoes until Sun 19 Oct. https://example.com/sale/trail-shoes?utm_source=sms&utm_medium=sms&utm_campaign=2026-10-autumn-sale&utm_content=list-a
→ 174 characters, 2 parts

To count your own message before you send it, paste it into the SMS character counter: it shows the parts, the encoding, the character that forced UCS-2 and what the link costs.

A bulk send through an SMS provider is a different case: read the trust note below before putting any shared shortener in it.

Write the link with https:// in front. Phones decide what to turn into a tappable link, and the scheme removes the guesswork.

Trust and filtering. In the US, CTIA's Messaging Principles and Best Practices (May 2023 edition) say that where a URL shortener is used in business messaging, senders "should use a shortener with a web address and IP address(es) dedicated to the exclusive use of the Message Sender" (CTIA, section 5.3.2). snu.to is shared by every SendURL user, and SendURL doesn't offer custom domains. So for bulk business texts to US numbers through an SMS provider, ask your provider before using any shared shortener, ours included. For WhatsApp, Telegram and texts you send from your own phone, that guidance doesn't apply.

UTM parameters for WhatsApp and SMS

whatsapp is on Google's list of social sources, and GA4 has a rule just for SMS: source or medium exactly sms (GA4 default channel group). Pair them so each lands in one channel without doubt:

Whereutm_sourceutm_mediumutm_contentGA4 channel
WhatsApp groupwhatsappsocialgroup-runnersOrganic Social
WhatsApp ChannelwhatsappsocialchannelOrganic Social
TelegramtelegramsocialchannelOrganic Social
SMSsmssmslist-aSMS

Don't mix the two, as in utm_source=whatsapp&utm_medium=sms. The visit then matches both the Organic Social and the SMS rules, and Google doesn't document which wins.

Tagged destinationsText
https://example.com/sale/trail-shoes?utm_source=whatsapp&utm_medium=social&utm_campaign=2026-10-autumn-sale&utm_content=group-runners
https://example.com/sale/trail-shoes?utm_source=telegram&utm_medium=social&utm_campaign=2026-10-autumn-sale&utm_content=channel
https://example.com/sale/trail-shoes?utm_source=sms&utm_medium=sms&utm_campaign=2026-10-autumn-sale&utm_content=list-a

The UTMs live in the destination. A query string added to the short link itself isn't passed on, and the short link stays short. More rules and examples are in the UTM parameters guide.

Checklist

  • One short link per group, Channel, Telegram channel and SMS list
  • Slugs with your own prefix, short enough to read: oct-sale-wa-runners
  • WhatsApp destinations tagged utm_source=whatsapp&utm_medium=social
  • SMS destinations tagged utm_source=sms&utm_medium=sms, never mixed with whatsapp
  • UTMs on the destination, not on the short link
  • Send time noted for every message; clicks in the first minute treated as previews
  • SMS written with https://, no emoji if you want 160 characters per part
  • Bulk business texts to US numbers: shortener checked with your SMS provider first
  • Per-person links only with a reason, and mentioned in your privacy notice

Shorten a link for your next message on the SendURL home page, or try the URL shortener with no sign-up.

Frequently asked questions

Can you see who clicked a link you sent on WhatsApp?

No. WhatsApp doesn't report link taps, and a tracked link records a click's time, country, device, browser, IP address and referrer, not the person. In a group, a click tells you someone in that group tapped it, not who.

Does a WhatsApp link preview count as a click?

On a tracked link that counts every visit, usually yes. WhatsApp builds the preview on the sender's phone when the link is pasted, so expect one extra click from your own device per message you compose with the link, within seconds of pasting.

Why does WhatsApp traffic show as Direct in Google Analytics?

A tap in a chat app opens the browser with no web page behind it, so there is no referrer to read. Without UTM parameters GA4 files the visit as Direct. Tag the destination with utm_source=whatsapp and utm_medium=social.

Can I use a short link in business text messages?

Yes, but in the US the carriers' trade group CTIA recommends a shortener on a domain used only by you for business messaging. snu.to is shared by every SendURL user, so check with your SMS provider before a bulk send.

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