A beauty academy knows which channel sells its course by tagging every link it shares with UTM parameters — utm_source, utm_medium and utm_campaign — capturing the first touch in the visitor's browser so the original source survives until she enrols, then reading source, medium and campaign against enrolments and revenue in Google Analytics 4 and the order export.
Here's the conversation I have with almost every academy owner I audit.
They're spending money on Google. They're spending money on Meta. Their educator is posting to 18K Instagram followers. They've got a blog, a Google Business Profile with 150 five-star reviews, and an email list they mail every couple of weeks.
Last month they enrolled 14 students. I ask: which channel produced them?
And the answer is always some version of "probably Instagram? Google says it got 9. Meta says it got 11."
Nine plus eleven is twenty. They sold fourteen. Both platforms are counting the same students, because both platforms are graded on their own homework. Meta claims a sale if the buyer saw an ad in the last seven days. Google claims it if there was a click in the last thirty. Neither of them knows the buyer also read your blog post, watched three Reels, and asked her sister about you.
So the founder makes budget decisions on numbers that are structurally wrong. They cut the channel that was actually doing the work — usually the top-of-funnel one that doesn't get last-click credit — and wonder why enrolments dropped.
Every ad platform reports on itself. Nobody is holding the single source of truth except you. UTM tags are how you build that source of truth — a tag you control, attached to the link, that travels with the visitor from first click all the way to a paid enrolment sitting in your orders list.
The good news: this is a one-afternoon job. It's not technical in the scary sense — most of it is copying a text string into a settings box. The part that separates a real setup from a half-setup is Section 11, and I'll walk you through that too.
One promise before we start: every step below is something you can do yourself. Nothing here needs a developer except one optional code snippet, and I've written that one out in full so you can paste it (it's in the free interactive version, below).
By entering your email you agree to receive the interactive version and occasional emails from me about filling beauty academy courses. One-click unsubscribe on every one, and your details are never shared. How I handle your data.
A UTM tag is just extra text on the end of your own link. Your page ignores it. Your analytics reads it. That's the whole mechanism.
A normal link to your course page:
https://youracademy.com/products/online-lash-course
The same link, tagged:
https://youracademy.com/products/online-lash-course?utm_source=instagram&utm_medium=bio_link&utm_campaign=online_course&utm_content=profile_button
Everything after the ? is the tag. The page loads exactly the same. But now when that person enrols, you know she came from your Instagram bio button — not "social," not "direct," not a guess.
There are five parameters. You'll use three of them constantly, two occasionally.
| Parameter | Answers the question | Beauty academy examples |
|---|---|---|
utm_sourcerequired | Which platform? The specific website or app the person was on before they clicked. | google · instagram · facebook · tiktok · youtube · email · gbp · chatgpt |
utm_mediumrequired | What type of marketing? Paid, organic, email, referral. This is what groups channels together in your reports. | cpc · paid_social · retargeting · social_organic · organic_search · email · bio_link · print |
utm_campaignrequired | Which offer or push? Tag it by the thing you're selling, not the month. | online_course · insalon_group · insalon_private · brochure · reactivation |
utm_contentrecommended | Which specific creative or link? The one that tells you what to make more of. | student_story_v2 · price_carousel · kit_unboxing · header_cta · email_07_pricing |
utm_termoptional | Which keyword or audience? Mostly auto-filled by Google Ads. On Meta, use it for the ad set. | lash+extension+course · warm_engagers_365d |
utm_content is the tag most people skip, and it's the one that makes you money. Source and medium tell you where to spend. Content tells you what to make. When you know that the student-story video produced six enrolments and the price-focused carousel produced zero, your next month of content writes itself.
Before you tag a single link, decide your vocabulary and write it down. This takes ten minutes and prevents the single most common failure: a year of data split across Instagram, instagram, IG, insta and Instagram Stories, all counted as five different channels.
Facebook and facebook are two separate rows in your report, forever.online_course, not online course. Spaces become %20 and make your links ugly and breakable.instagram is a place. paid_social is a method. If you find yourself putting "instagram_ads" in source, split it.insalon_group, not march_promo. Offers persist; months don't, and you'll want to compare this March to next March.fb to facebook six months in doesn't merge the old data — it strands it.If a visitor arrives from Google (tagged google / cpc) and then clicks a button on your homepage that you've tagged utm_source=homepage, most analytics tools will end her session and start a new one — and credit the enrolment to "homepage" instead of Google. You've just erased your own ad data with your own button.
UTMs are for links that point at your site from somewhere else. For measuring buttons inside your site, use event tracking, not UTMs. The only exception: a link on your site pointing at a genuinely different domain you also own (e.g. your booking system on another host).
Copy this into a sheet and treat it as law. Add rows, don't rewrite them.
| utm_source (the place) | utm_medium (the method) | utm_campaign (the offer) |
|---|---|---|
google | cpc — paid search | online_course |
facebook | paid_social — cold ads | insalon_group |
instagram | retargeting — warm ads | insalon_private |
tiktok | social_organic — unpaid posts | brochure — lead magnet |
youtube | organic_search — SEO | reactivation — old list |
email | email | waitlist |
sms / whatsapp | dm — direct messages | refresher_course |
gbp — Google Business Profile | bio_link | kit_upsell |
blog | referral — partners, press | open_day |
qr | print — cards, flyers, inserts | student_referral |
partner_name | affiliate |
This is your reference sheet. Every place an academy gets traffic, and exactly what to tag it with. The next five sections show you where to paste each one.
| Where the link lives | What to tag it with | Where you paste it |
|---|---|---|
| Google Search ads | source=google · medium=cpccampaign, content, term auto-filled | Final URL Suffix (account or campaign settings) |
| Meta cold ads | source=facebook · medium=paid_social | Ad level → Tracking → URL parameters |
| Meta retargeting | source=facebook · medium=retargeting | Ad level → Tracking → URL parameters |
| Instagram bio link | source=instagram · medium=bio_link | A short redirect on your own site (see §07) |
| Instagram Story link stickers | source=instagram · medium=social_organic · content=story_<topic> | Story sticker URL, or a redirect |
| Instagram DM auto-replies | source=instagram · medium=dm · content=<keyword> | Your DM automation reply text |
| Email broadcasts | source=email · medium=email · campaign=<offer> | Global UTM setting in your email tool |
| Email automations | content=<sequence>_<number> | Per-email override |
| Blog posts → course pages | ⚠️ Do not tag — these are internal links | — |
| Guest posts / press | source=<publication> · medium=referral | The link you give them |
| YouTube descriptions | source=youtube · medium=social_organic · content=<video_slug> | Description + pinned comment |
| Google Business Profile | source=gbp · medium=organic_local | Website field + every GBP post |
| QR codes (cards, flyers, salon) | source=qr · medium=print · content=<where_it_is> | The URL you encode |
| Kit / welcome-pack inserts | source=qr · medium=print · campaign=student_referral | The printed QR |
| Partner colleges & salons | source=partner_<name> · medium=referral | The link you give the partner |
| WhatsApp / SMS follow-ups | source=whatsapp · medium=dm · content=<stage> | Your message template |
The partner referral row is worth more than it looks. Beauty academies quietly get a lot of business from local salons, TAFE-adjacent colleges, and past students who send friends. Almost none of it is measured, so it never gets invested in. Give each partner their own tagged link, and within a quarter you'll know which relationship is actually worth nurturing — and which "partnership" has sent you nothing in two years.
Google Ads has a dedicated field for this. You set it once at the account level and every ad in every campaign inherits it. Five minutes, done forever.
? at the start — Google adds it.utm_source=google&utm_medium=cpc&utm_campaign={campaignid}&utm_content={creative}&utm_term={keyword}
Those curly-brace items are Google's ValueTrack parameters. Google swaps each one for the real value at click time, so you never have to tag ads individually.
| ValueTrack | Becomes |
|---|---|
{campaignid} | The numeric ID of the campaign that got the click |
{creative} | The ID of the specific ad |
{keyword} | The keyword that triggered it |
{network} | g = Google search, s = search partners, d = display |
{device} | m = mobile, t = tablet, c = computer |
1. Do you already have a tracking template? Some agencies install click-fraud or call-tracking software as a tracking template, which wraps every click through a third-party domain. If that field has something in it, leave it alone and put your UTMs in the Final URL suffix instead. The suffix appends after the redirect, so both survive. Deleting an inherited tracking template can silently break someone else's tool.
2. Leave auto-tagging ON. Google's own gclid is separate from UTMs and is what powers conversion import and Enhanced Conversions. You want both. They don't conflict.
{campaignid} gives you a number like 21738904511, not a name — Google has no ValueTrack for campaign name. Two options:
utm_campaign=online_course on the online-course campaign and utm_campaign=insalon_group on the in-salon one. Campaign-level settings override account-level ones.For a typical academy with three or four campaigns, option two is worth the ten extra minutes.
Meta's equivalent field lives at the ad level, not campaign level — so you'll paste it once per ad. Meta has its own dynamic parameters, which means you can still write one string and reuse it everywhere.
?.utm_source={{site_source_name}}&utm_medium=paid_social&utm_campaign={{campaign.name}}&utm_content={{ad.name}}&utm_term={{adset.name}}
utm_source={{site_source_name}}&utm_medium=retargeting&utm_campaign={{campaign.name}}&utm_content={{ad.name}}&utm_term={{adset.name}}
The only difference is medium. Keeping cold and warm traffic in separate mediums is what lets you answer the question that actually matters: is my retargeting closing people my cold ads found, or is it just harvesting people who were going to buy anyway?
| Parameter | Becomes |
|---|---|
{{site_source_name}} | fb, ig, an (Audience Network) or msg — so you can finally see whether Facebook or Instagram placements produce your enrolments |
{{campaign.name}} | The campaign name exactly as you typed it |
{{adset.name}} | The ad set name — i.e. your audience |
{{ad.name}} | The ad name — i.e. your creative |
{{placement}} | Feed, story, reels, etc. |
Because {{campaign.name}} and {{ad.name}} pass through verbatim, a campaign called Campaign — Copy (2) FINAL v3 becomes a UTM value called Campaign — Copy (2) FINAL v3. Spaces, brackets and all.
Fix it at the source: name your Meta assets in the same lowercase-underscore style you set in Section 03. Something like online_course_cold / warm_engagers_365d / student_story_v2. Then your ad manager and your analytics speak the same language, and you can match a row in one to a row in the other without translating.
For most beauty academies this is the biggest single traffic source and the worst tracked, because you can't paste a 140-character link into a bio and have it look professional.
The fix is a redirect on your own domain. You share a short, clean link. Your site quietly forwards it to the real page with the tags attached.
| You share | It forwards to | Use it for |
|---|---|---|
youracademy.com/ig | /products/online-course?utm_source=instagram&utm_medium=bio_link&utm_campaign=online_course&utm_content=profile_button | The link in your bio |
youracademy.com/ig-story | ...&utm_medium=social_organic&utm_content=story_sticker | Story link stickers |
youracademy.com/ig-dm | ...&utm_medium=dm&utm_content=dm_reply | DM replies and auto-responders |
/ig. "Redirect to" = the full tagged path./ig -> /products/online-course?utm_source=instagram... 301Three reasons. It keeps the visitor on your domain, so your retargeting pixel fires on the click instead of on a third-party page. It removes an entire tap from the journey — link-in-bio pages lose a meaningful share of visitors at the menu screen. And it means you can change where /ig points during a launch without editing your bio or waiting for Instagram to re-approve anything.
If you run "DM me KIT to get the details" style funnels, give each keyword its own utm_content: content=dm_kit, content=dm_price, content=dm_dates. You'll learn which question people are actually asking before they buy — which is the raw material for your next ad, your FAQ section, and your objection-handling emails.
Every serious email platform can append UTMs automatically to every link in every email. Turn it on once:
Set the global defaults to utm_source=email and utm_medium=email. Then override utm_campaign per broadcast and utm_content per email inside a sequence — content=nurture_03, content=cart_02, and so on. Now you can see which email in a nine-email sequence produces enrolments, and cut the seven that don't.
Clicks from desktop mail apps often arrive with no referrer at all. Untagged, your entire email programme disappears into the "direct / none" bucket — the same bucket as people typing your URL from memory. Academies routinely conclude "email doesn't work" when the truth is email was never labelled.
Do not UTM-tag links from your blog to your own course pages. That's internal, and per Section 03 it wipes out the original source. Your blog's contribution shows up correctly as the landing page in your analytics without any tagging.
Do tag links you place on other people's sites: guest posts, directory listings, press features, industry roundups. utm_source=<publication>&utm_medium=referral.
Tag the description link and the pinned comment separately so you can see which one people actually use:
https://youracademy.com/products/online-course?utm_source=youtube&utm_medium=social_organic&utm_campaign=online_course&utm_content=desc_how_to_start
Your GBP is often the highest-intent traffic you get — someone searching your academy by name, or "lash course near me," and clicking through from the map panel. Tag it:
?utm_source=gbp&utm_medium=organic_local&utm_campaign=profileutm_content=post_<topic>utm_content=gbp_bookingDo this and your local search performance stops hiding inside "organic."
People increasingly find academies by asking ChatGPT, Perplexity or Gemini for a recommendation. Those clicks arrive with a referrer you can watch for even though you can't tag them — add chatgpt.com, perplexity.ai, gemini.google.com and copilot.microsoft.com to your referrer rules in Section 11, and they'll get labelled automatically. It's a channel most academy owners don't know they already have.
This is the tracking nobody does, and it's the reason "word of mouth" stays permanently unmeasurable in a beauty business.
| Physical thing | Tag |
|---|---|
| Review-request card handed out at graduation | source=qr&medium=print&campaign=reviews&content=grad_card |
| Card inside the student kit box | source=qr&medium=print&campaign=student_referral&content=kit_insert |
| Poster / window sign in the salon | source=qr&medium=print&campaign=insalon_group&content=salon_poster |
| Flyer at a beauty expo or trade show | source=qr&medium=print&campaign=online_course&content=expo_<name> |
| Business card | source=qr&medium=print&content=business_card |
Build the tagged URL first, then generate the QR code from that exact URL. Any free QR generator works — the tag is in the link, not the code.
A long tagged URL makes a dense QR code that's slower to scan in bad light. Point the QR at a short redirect on your own domain instead — youracademy.com/kit → the tagged URL. Simpler code, scans instantly, and you can change the destination later without reprinting a thousand cards.
Give every referring salon, college, and ambassador their own link: utm_source=partner_bellasalon&utm_medium=referral&utm_campaign=insalon_group. No commission structure needed to start — just measure it for one quarter. You'll be surprised which relationships are carrying real weight and which are ceremonial.
The interactive version of this guide has a link builder: fill in the fields, copy the link, paste it wherever it's going. It follows the naming rules from Section 03 automatically — lowercases everything and swaps spaces for underscores.
Get the interactive version free: the UTM link builder that writes your tagged links for you, plus the first-touch capture script and the CRM field mapping, ready to paste.
Unlock the interactive version →Every link you build goes in one spreadsheet. This is what stops your taxonomy drifting six months from now when you're building links at speed, or when someone else on your team starts making them.
| Date | Where it's used | Source | Medium | Campaign | Content | Full URL | Live? |
|---|---|---|---|---|---|---|---|
| 03 Mar | IG bio button | bio_link | online_course | profile_button | paste | Yes | |
| 03 Mar | Kit box insert QR | qr | student_referral | kit_insert | paste | Yes | |
| 11 Mar | Bella Salon referral | partner_bellasalon | referral | insalon_group | — | paste | Yes |
Everything above is the standard advice. This section is what separates a setup that survives contact with reality from one that quietly produces garbage.
Problem one — the tag dies at the first click. A visitor lands from your Google ad with a beautiful tagged URL. She reads for four minutes, doesn't buy, and closes the tab. Two days later she comes back by typing your name into Google and clicking the organic result. She buys. Your analytics credits organic. The ad you paid for gets nothing.
Problem two — most traffic has no tag at all. You can only tag links you control. Someone who screenshots your Reel and searches for you later, or hears about you from a friend, or clicks a link a student pasted in a Facebook group, arrives with no tag. Untreated, all of it collapses into "direct / none," which is where attribution goes to die. In most academies I audit, "direct" is the single largest channel — and it's not a channel, it's a measurement failure.
Problem three — the tag never reaches the order. Even a perfectly tagged visitor loses the tag at checkout, because your checkout usually lives on a different subdomain. So your orders list, the one place with the actual money in it, has no idea where any of it came from.
One script on your site that does three things:
instagram / social_organic. From google.com? google / organic_search. From chatgpt.com? chatgpt / ai_search. Your "direct" bucket shrinks to the people who genuinely typed your URL.The first-touch script is pasted into your site's <head> — in Shopify that's layout/theme.liquid just before </head>; in WordPress, a header-scripts plugin; anywhere else, wherever your other tracking tags live. It's plain JavaScript, works on any platform, and every part of it fails silently so it can never break your checkout.
Get the interactive version free: the UTM link builder that writes your tagged links for you, plus the first-touch capture script and the CRM field mapping, ready to paste.
Unlock the interactive version →OWN_HOSTS. Put your real domain in, plus your checkout subdomain if you have one. This stops your own pages being counted as referrals.toCart listeners and use window.getAttribution() to fill hidden form fields instead (next section).Open your site in a private window with a test tag on the end — ?utm_source=test&utm_medium=test. Then open DevTools (right-click → Inspect) → Application tab → Local Storage → your domain. You should see keys starting ft_ holding your test values.
Now visit again without the tag. The values should stay test — that's the lock working. Clear local storage, arrive from an Instagram link, and you should see instagram / social_organic appear on its own.
A stored value in a browser is only useful if it ends up attached to a human in your systems. Two places it needs to land.
Add five hidden fields to your opt-in forms, popups and enquiry forms, then fill them from storage on submit. Works with Kit, Klaviyo, Mailchimp, Typeform, a custom form — anything that accepts hidden fields.
Get the interactive version free: the UTM link builder that writes your tagged links for you, plus the first-touch capture script and the CRM field mapping, ready to paste.
Unlock the interactive version →In your email platform, create matching custom fields (utm_source, utm_medium, utm_campaign, utm_content, first_touch_date) so the values have somewhere to land. Now every subscriber record shows how that person found you — and you can segment your list by channel, which is a genuinely different way to write email.
If you're on Shopify, the cart block in Section 11 does this for you. The values ride the cart into checkout and appear on the order under Additional details in the order page — and in your CSV order export.
That's the moment the whole system pays off: you can open your orders for the month, sort by utm_source, and see the actual dollar value each channel produced. Not the platform's claim. Yours.
If you run a CRM for in-salon enquiries — where the enrolment happens on a call rather than a checkout — create six custom fields on the lead record:
Then map them in whatever pushes leads into the CRM (Zapier, Make, a native integration). Add a simple lookup step that converts utm_source into a friendly "Lead Source" dropdown value — google → "Google Ads", instagram → "Instagram", empty → "Direct" — so whoever works your leads sees plain English, not parameters.
Your online course tracks itself — it's a checkout. Your high-ticket in-salon courses usually close over DM or a phone call, which means the most profitable enrolments are the least measured ones. Getting the first-touch tag onto the CRM record is how you find out that the ads you thought were "only" driving online sales are actually feeding your in-salon pipeline too.
Reports → Acquisition → Traffic acquisition. Change the first dropdown to Session source / medium. That's your channel table. Add Session campaign as a secondary dimension to break it down by offer.
For creative-level insight, build one exploration and save it: Explore → Blank, rows = Session source / medium and Session manual ad content, values = Sessions, Key events, Total revenue. That single table answers "which creative produced money" in one screen.
If you did Section 11, this is the honest report. Export your orders to CSV, and you'll have the attribution columns sitting next to the order value. Pivot by utm_source, sum the revenue. That's your real channel P&L — every dollar counted once, by you.
Once a month, put three numbers side by side for each channel:
| Channel | Platform claims | Your first-touch data says | Spend | Real cost per enrolment |
|---|---|---|---|---|
| Google Ads | 9 enrolments | 6 | $2,400 | $400 |
| Meta retargeting | 11 enrolments | 3 | $600 | $200 |
| Instagram organic | — | 4 | $0 | $0 |
| — | 1 | $0 | $0 |
Illustrative numbers. But the shape is what you'll almost always see: the platforms over-claim, retargeting looks heroic until you notice it's re-closing people another channel already found, and organic quietly carries more than anyone gave it credit for.
Your first-touch numbers will be lower than the platforms' numbers, and that's correct — you're counting each enrolment once. Platform figures are still useful for optimising inside a platform (which ad, which keyword). Your data is what you use to decide between platforms. Use each for the job it's honest about.
Instagram, instagram and IG become three separate channels. Lowercase everything, always.OWN_HOSTS — your own checkout appears as the referrer on every order.In order. Each one is a step you can finish before starting the next.
Give it two to four weeks of traffic before drawing conclusions. Attribution needs volume before the pattern is real — one week of data on a small account will mislead you more than no data at all.
I audited 80 beauty academies and not one had a complete funnel. If you want a second set of eyes on your tracking — or on the funnel it's meant to be measuring — book a free academy audit and I'll walk you through exactly what's leaking and what to fix first.
Book your free academy audit →Asbaat Amar · BeautyAcademyScaler