The honest answer is that it depends on what you are doing, and that inconsistency is exactly why casing causes so much quiet trouble.
Three operations, three different behaviours:
| What you are doing | How casing behaves |
|---|---|
| Adding a tag | Folded. You cannot end up with both VIP and vip on one record |
| Searching or segmenting | Ignored. A search for vip matches a record tagged VIP |
| Removing a tag by API | Exact. A removal for vip does not match VIP |
Two of those are forgiving. The third is not, and it fails silently.
None of it is documented by Shopify — the section below quotes what the official docs actually say. Everything here is observed behaviour, dated, from building against the Admin API.
Adding: the first casing wins
If a record already carries VIP and something adds vip, you do not get two tags. Shopify folds them, and the casing already on the record is the one that survives.
We watched this happen on a live store in August 2026, during a migration that rewrote a large batch of tags. A customer was already carrying a seeded VIP. Our migration compared case-sensitively, decided vip was missing, and added it. Shopify folded the two and kept VIP.
Nothing was lost and the end state was correct — but the count our migration reported was not what actually happened on the store. The tag you send is not necessarily the tag you end up with.
Searching: casing is ignored, which is what hides the problem
A customer segment or a tag: filter written in lower case still matches records tagged in any other casing. That is genuinely helpful, and it is also why casing problems can sit undetected for months: your segments keep returning the right people, so nothing looks broken.
Removing: exact match, and this is where it bites
Removal through the Admin API matches the string you give it. If the record carries VIP and your removal asks for vip, there is nothing to match. The removal succeeds, reports no error, and the tag is still there.
Then everything downstream keeps working as though nothing happened:
- the customer segment still matches, because search ignores case
- every email flow reading that tag still fires
- the discount tied to it still applies
- and the record looks correct at a glance, because the tag it carries is the tag you meant
This is the failure worth designing against. An add that misfires is visible. A removal that misfires looks exactly like success.
What Shopify's own documentation says
Almost nothing, and that is the point.
tagsAdd— "Adds tags to a resource. If the resource type doesn't support tagging, theidargument returns a resource-not-found error."tagsRemove— "Removes tags from a resource. If the resource type doesn't support tagging, theidargument returns a resource-not-found error."- Shopify Help Center: tags — covers which characters to use, tag length and keeping tags clear.
We read all three on 17 August 2026. None of them mentions capitalisation, case sensitivity, or what happens when you add a tag that differs from an existing one only by case. The merchant-facing guidance says to use "ordinary letters, numbers, and the hyphen" and stops there.
So the behaviour described on this page is not documented anywhere official. It is what we have observed building against the API — which is exactly why it is worth writing down, and why you should verify it against your own store rather than taking any blog's word for it, including this one.
Four ways this actually happens
None of these are hypothetical. Each is a different source writing tags with a different convention.
Another app uses its own casing. A reviews app tags Verified-Buyer, a loyalty app tags verified-buyer, and your cleanup rule asks to remove Verified Buyer. Three conventions, none of them wrong on its own, and a removal that matches none of them. This is the most common version, because you do not control the other app's convention and it can change under you in an update.
A CSV import carries the spreadsheet's casing. Someone exports customers, edits in Excel, re-imports. Excel's autocorrect capitalises the first letter of a cell, so vip goes out and Vip comes back, on a few thousand records at once.
A person types it by hand. Someone tags a customer in the admin at the end of a long day. VIP today, vip next week. Neither is wrong; they just are not the same string.
Your own rules disagree with each other. A rule written last year applies wholesale. A rule written this month removes Wholesale. Both look correct in isolation, and together they do nothing.
The pattern is the same each time: the tag gets applied by one thing and removed by another, and the two never agreed on spelling.
Cleaning up casing you already have
If your store already has three spellings of the same tag, you do not have to fix them by hand.
A rule that applies your canonical spelling and removes that same tag will normalise the record: the removal is expanded against the tags the record actually carries, matched without regard to case, while the exact spelling the rule is applying is protected from its own removal.
So on a customer carrying VIP, a rule that applies vip and removes vip:
- finds
VIPon the record, because the comparison ignores case - does not protect it, because
VIPis not the spelling being applied - removes
VIPusing that exact string, which is what the API needs to match - applies
vip
The record ends up with one tag, spelled the way you decided. Run it across a target and the whole store converges on one convention.
The reason this works is unglamorous: the removal is resolved against what is really on the record, not against what the rule was written in. A cleanup that sends a fixed string can only ever remove the casing whoever wrote the rule happened to use.
Two honest limits. This normalises the tags your rules name — it is not a bulk "lower-case every tag on the store" button, and there isn't one. And it changes real records, so preview it against a real record first and watch what comes off before you run it across a catalogue.
Why one convention matters beyond your own store
Once every record spells a tag the same way, every tool that reads it exactly agrees with every other one.
Be precise about which tools those are, because it is not all of them. Anything that searches — Shopify segments, tag: filters, most reporting — was never broken by mixed casing, since search ignores case. What mixed casing breaks is anything doing an exact string match:
- an app removing a tag it did not apply
- a Flow condition comparing a tag to a literal
- an export feeding a system that matches on the exact string
- a theme or app reading
product.tagsand comparing directly
Those are the ones that silently disagree today and quietly agree once the spelling is settled. Normalising does not make apps talk to each other — they were always reading the same field. It removes the reason they read it differently.
This is one of the cases we test against
The behaviour on this page is not something we inferred from documentation, because as noted above there isn't any. It is a scenario we build and test against directly: a record carrying one casing, a rule written in another, and the assertion that the cleanup strips every variant on the record while protecting the exact spelling being applied.
It is in the test suite precisely because it is the kind of thing that looks fine in a demo and fails on a real store six months later, on records tagged by someone who left.
What to do about it
Pick one convention and write it down. Lower case is the usual choice, because it is the easiest to type the same way twice. The specific choice matters far less than everyone making the same one.
Never assume the casing on a record. The record may have been tagged before your convention existed, by someone who never heard of it.
Make removals look at what is really there. This is the important one. A removal should be expanded against the record's actual tags, compared case-insensitively, rather than sending a fixed string and hoping it matches. It is the difference between "remove the vip tag" meaning what a merchant means by it, and meaning "remove the tag if it happens to be spelled the way I wrote it".
That is how Rules2Tag handles it: a rule that removes vip is expanded against the tags the record actually carries, so it catches VIP and Vip too. Tags the same rule is currently applying are protected from its own removal, so a rule that both applies and removes a spelling reads as "this spelling wins" rather than as a contradiction.
Preview before you run. A casing mismatch is obvious the moment you can see what a change would do to a real record, and invisible until then.
The short version
Shopify tags are case-insensitive when you add them and when you search them, and case-sensitive when you remove them. Two out of three behaviours quietly forgive a mistake, and the third quietly keeps it — which is why a tag you are certain you removed can still be sitting on the record, still matching every segment that reads it.