How a Value Behaves
Analytics reads every value literally: by the exact string, sorted as text, split where you put separators. What that means for case, dates, delimiters and the lists you allow.
On this page
The Q3 pipeline review. Priya, the VP of Marketing, pulls up the channel slide and asks: “Should we shift budget from LinkedIn to Google next quarter?”
Megan, the analyst, hesitates. She knows the LinkedIn numbers are split across four spellings, linkedin, LinkedIn, li and linked-in, and she can’t say by how much without hours of cleanup.
The room makes the call anyway. $25K moves from LinkedIn to Google.
That company is a composite of teams we’ve worked with: a 40-person B2B software firm, five marketers, about $180K a quarter of paid spend. Nobody had ever decided which values were allowed in a link.
So each marketer typed what seemed right at the time.
Chapter 2 ended on two questions: which values go in those five fields, and who decides? Most teams answer the first one with a shrug. Values are labels. Any sensible spelling will do, and lowercase, year-first dates and underscores are matters of taste.
They aren’t, because your analytics doesn’t read values the way you do.
Sort the report and look
Here’s a small campaign report, sorted A to Z by campaign, the way any report or spreadsheet sorts text:
| Campaign | Source |
|---|---|
spring_sale-shoes-03_2025 | Facebook |
spring_sale-shoes-03_2025 | facebook |
spring_sale-shoes-09_2024 | facebook |
summer-sale-shoes-2025_06 | newsletter |
Three questions. Answer them before you open the reveal.
- How many different sources does Facebook show up as?
- Which spring flight launched first?
- A program that splits campaign names on their hyphens reads the second piece as the product. What product does it find in the last row?
Show the answersHide the answers
- Two.
Facebookandfacebookare different strings, so they’re different rows, and every total for the campaign is split between them. - September 2024, the lower of the two spring rows. The report sorted the characters, and
03comes before09, so March 2025 sits above the flight that ran six months earlier. sale. Split on hyphens,summer-sale-shoes-2025_06comes apart into four pieces,summer,sale,shoesand2025_06, and the second one issale.
Look at the campaign column again. Both Facebook rows say spring_sale-shoes-03_2025, spelled exactly alike, and the source column still splits Facebook in two. Whoever made those links probably copied the campaign value from the plan and typed the source by hand. A report grouped by campaign looks clean, and the split only shows when you open its source breakdown.
Nothing in that report is broken. Every row is exactly what someone typed.
Analytics reads the string, not the meaning
The three surprises have one cause. Your analytics and every tool behind it read a value as a string of characters. It doesn’t know what you meant. It knows what you wrote.
It groups by the exact string. In GA4’s reports and in a warehouse such as BigQuery or Snowflake, Facebook and facebook are two rows. GA4’s channel rules ignore case, so both might land in the right channel, and the source column still splits in two.
One spelling, one row.
It sorts as text. A report sorts characters, not dates, and dates go wrong three ways:
- Month first: March 2025 sorts above September 2024 (
03_2025before09_2024). - Month names: April sorts before January (
aprbeforejan). - No zero: March sorts after October (
2025_3after2025_10).
Only one form sorts by time: year first, zero-padded. 2025_03 for a month, 2025_q2 for a quarter, 2025_03_14 for a day.
It splits only where your separators allow. Anything that has to pull a name apart again, a spreadsheet formula or a warehouse query, needs to know where one piece ends and the next begins. So the book uses two delimiters with two jobs: underscores join the words inside one segment, and hyphens separate segments. summer_sale-shoes-2025_06 splits into three whole pieces. summer-sale-shoes-2025_06 splits into four, and no program can put summer and sale back together. Mediums follow the same rule, because a medium often ends up inside a longer name, where a hyphen would split it: it’s paid_social, never paid-social.
One fact per slot. A value carries its own slot’s fact and nothing else. If the source is facebook, the medium isn’t facebook_social. Keep each slot to its own fact and every slot can be grouped and filtered on its own; cram two facts into one and neither can.
Here’s what those rules catch on a single hand-typed link, value by value:
| Typed by hand | From the list |
|---|---|
Facebook | facebook |
Social Media | social |
Summer Sale 2025! | summer_sale-shoes-2025_06 |
The capital letter makes a second Facebook row in every report. The spaces make another spelling of each value. And ! is outside the safe characters (letters, digits, underscores and hyphens).
A value means what you agreed, and what the tool decides
The string is what the tool sees. The meaning is what your team agreed it stands for, plus what the tool’s rules make of it.
paid_social and social are different channels because your list says so: one is a paid ad, the other an organic post. GA4 agrees: its channel rules (Chapter 2) put a paid medium from a social source in Paid Social and social in Organic Social. When the list and the tool agree, the report means what you meant.
Two things share the word channel. Dana’s channel dimension from Chapter 1 is a fact her team decides. GA4’s is the tool’s grouping of source and medium. They match only because the medium list was built to make them match. Tag a paid Facebook ad social by mistake and they come apart: the ad was paid social to Dana and Organic Social to GA4.
The medium list
This book’s mediums are written for GA4’s rulebook. GA4 calls a medium paid when it starts with paid or contains cp, like cpc (or is exactly ppc or retargeting). Then the source picks which paid channel: cpc needs a search source to land in Paid Search, paid_social a social source, paid_video a video source. A paid medium from a source GA4 doesn’t recognize lands in Paid Other. Every medium below but offline passes GA4’s default rules:
| Medium | Use for | GA4 default channel |
|---|---|---|
cpc | paid search | Paid Search |
paid_social | paid social | Paid Social |
paid_video | paid video, such as YouTube ads | Paid Video |
social | organic social posts | Organic Social |
video | organic video descriptions and cards | Organic Video |
email | every email | |
display | display and banner ads | Display |
affiliate | affiliate links | Affiliates |
referral | partner links, guest posts, event apps | Referral |
audio | podcast show notes and ads | Audio |
offline | QR codes, print, events, direct mail | Unassigned, unless you add a custom channel group |
offline is the one deliberate exception: GA4 doesn’t recognize it, and it’s on the list anyway, because printed codes and event signage deserve their own bucket. A custom channel group gives them one.
Sources are simpler: the platform or property, lowercase.
- Platforms:
google,bing,facebook,instagram,linkedin,twitter,tiktok,youtube - Your own emails:
newsletter,promotional_email - Offline:
retail_display,direct_mail,print_ad,event - With a detail:
partner-acme,affiliate-jane_smith,podcast-marketing_over_coffee
A source can add one detail after a hyphen, to name the third party that publishes the link. Where your own printed material sits is a placement, and it goes in utm_content: Stride’s QR code at Fleet Feet NYC is source retail_display, content fleet_feet_nyc-qr_code.
The two lists aren’t independent. Each medium takes only some sources: email comes from newsletter or promotional_email, never from facebook, and social comes from facebook or instagram, never from newsletter. Both values in newsletter / social are on the list, and the pair is still wrong: GA4 files any social medium under Organic Social, so the newsletter’s clicks read as organic posts. So the list holds pairs as well as values: for each medium, the sources it allows. A builder can then offer only those sources once the medium is picked (Chapter 9).
Some teams go leaner, with one paid medium and the source saying which channel: facebook plus paid is paid social, google plus paid is paid search. GA4 copes, since paid matches its paid rule. Anything that reads only the medium can’t, so a warehouse would need a lookup from source to category to tell the paid channels apart.
Either is a fine choice.
As long as it’s a choice.
Closed list or open list
Which values go in the fields is half of Chapter 2’s question. The other half is who decides, and that comes down to what happens when someone needs a value the list doesn’t have. A controlled vocabulary is the list of allowed values for each slot. It runs one of two ways:
Closed
A value that isn’t on the list isn’t used. Someone has to add new ones, and every link stays consistent.
Lean this way when many people type values, or anything parses them: every new spelling becomes a new row.
Open
Anyone types what seems right. Nothing slows a launch down, and the values drift apart.
Lean this way when one person makes every link, or when a tool holds the format and a stray new word costs little. Either way, write the list down.
Open doesn’t have to mean unformatted. A tool can hold the format on an open list: it lowercases what’s typed and turns spaces into underscores, so Spring Sale arrives as spring_sale. It can’t stop a new word, though: fb is well formed, and it still isn’t facebook.
The LinkedIn company ran open without ever deciding to, and it cost them $25K of budget moved on a number nobody could trust. A closed list needs someone who adds the values, and owning that job is Chapter 10’s subject. For now it’s one sentence:
If it isn’t on the list, ask before you use it.
One pattern for campaign names
Sources and mediums are short lists. Campaigns are the one slot where a team writes a new value for every initiative, so this is where free names do the most damage. The alternative is a naming pattern: one shape every campaign name follows.
[initiative]-
spring_sale-runners-2025_03webinar-product_demo-2025_04brand_awareness- lifestyle- 2025_04
Free names cost nothing to write and everything to read: no two people’s names sort or split the same way. A pattern costs a minute of thought per campaign and gives every name the same shape. Teams usually move through three levels:
- Plain names:
spring_sale. - Names with a date:
spring_sale-2025_03. - Names with several segments, like the pattern above.
If nothing ever sorts or splits your names, plain is enough.
If anything does, use a pattern.
This pattern is how Stride gives product line a home. Chapter 2 found that product line had no slot of its own; here it shares the campaign slot as its own segment, runners, and stays splittable.
The date is the launch. A running campaign keeps its value until it ends, however long it runs. Rename it in April and it becomes two strings, which means two rows, and no single row holds its total. A relaunch is the opposite case: when the sale comes back as a new flight, it gets its own launch date (spring_sale-shoes-2025_09), and the two flights sit side by side, comparable and distinct.
The pattern carries initiative, product and date. There’s no region in it.
That three-segment pattern is already a small structure, and Chapter 4 picks up the idea.
Here is Stride’s list as a live builder, built in Terminus. Open the dropdowns: these are the values Dana picked, and the only ones on offer.
All of this happens before a single visit is recorded. The values are decided at the moment a link is made, and read at stage 3, where the visit lands:
Your situation
What you need depends on a few things you can check today:
- If several people type values, or new values arrive often, a closed list pays for itself fastest: every new value would otherwise arrive in whatever spelling its typist picked.
- If anything parses your names (a warehouse query, Adobe classification rules on a
cid), the delimiters are what the parser depends on. - If your reports sort campaigns, the date format decides whether last year and this year line up.
- Whichever analytics tool you use, its channel rules decide what your mediums mean. GA4’s are the ones above.
What changes
| The decision | Values as labels | Values read literally |
|---|---|---|
| Spelling | style, cleaned up later | a decision about how reports group, sort and split |
| Who types values | anyone, whatever seems right | from a list, closed or open, chosen on purpose |
| Campaign names | whatever reads well that week | one pattern, with the date as the launch, wherever anything sorts or parses them |
| Mediums | whatever describes the channel | values the tool’s rules understand, or your own channel groups, chosen on purpose |
Read down the right-hand column. Every cell is a decision, made on purpose. Which values you pick matters less than picking them; the LinkedIn company moved $25K on a number it never decided how to spell.
Where the rule lives
Back to the pipeline review and the $25K.
After that meeting, the company did two things. It wrote down a controlled vocabulary for each parameter, and it moved all link-making into one builder whose dropdowns offered only those values. Within one quarter, duplicate source entries in its reports went from 47 to zero.
Then Megan merged the old LinkedIn rows, and the history told a different story. Per dollar, LinkedIn had produced three times the pipeline of paid search. The $25K had gone to the weaker channel, and nobody could see it until the data was clean.
The list of approved values can live in one of two places:
Beside the path
Written in a sheet, it’s a rule people have to remember every time they make a link.
Inside the path
Built into the builder’s dropdowns, a value that isn’t on the list can’t be typed.
Check yourself
Two flights of one campaign, spring_sale-shoes-09_2024 and spring_sale-shoes-03_2025, sort A to Z with the 2025 flight on top. Why, and what values would sort them by launch?
Show answerHide answer
The report compares characters, and 03 comes before 09, so March 2025 lands above September 2024. Write the year first: spring_sale-shoes-2024_09 and spring_sale-shoes-2025_03 sort in launch order.
A program splits summer-sale-shoes-2025_06 on its hyphens and reads the second piece as the product. How many pieces does it get, and what product?
Show answerHide answer
Four pieces, and the product reads sale. With underscores inside segments, summer_sale-shoes-2025_06 splits into three whole pieces, and the product is shoes.
A new hire tags a LinkedIn ad linkedin / linkedin_paid. Which rules does it break, and where do the visits land?
Show answerHide answer
The medium repeats the source, and it isn’t on the list. It also doesn’t read as paid: it neither starts with paid nor contains cp, so GA4’s paid rule doesn’t match it. The social source decides, and the visits land in Organic Social. Use paid_social.
In one line
Analytics reads a value literally: it groups by the exact string, sorts it as text and splits it where you put separators. Every convention is a decision about your reports, so make each one on purpose, and decide whether your list of values is closed.
Before the next chapter
Sort your campaign report A to Z and find one place where the order, the spelling or a split surprises you. That's a convention your team hasn't decided yet.