Custom Short Link Slugs: Naming Rules That Work in Print
Part of the QR & print handbook
What makes a good custom short link: the seven rules, SendURL's exact slug rules, why case matters, which characters to avoid, and naming patterns with examples for launches, sales, podcasts, events and print.
A good custom short link slug is lowercase, made of one to three real words joined by hyphens, free of characters that look alike, and used for exactly one placement. On SendURL a slug is 1 to 32 letters, digits, hyphens or underscores, it is case-sensitive, and it can never be changed after the link is created, so the choice matters most for links that get printed, typed or read aloud.
The slug is the part after the domain: in snu.to/autumn-sale-ig-bio it's autumn-sale-ig-bio. The domain is always snu.to; SendURL has no custom domains. This guide is part of the QR and print handbook, next to how to track QR code scans, and it's linked from the social media link tracking handbook, because slugs matter most wherever people have to type a link.
Random or custom slug?
Every SendURL link gets a random slug unless you type one. Random slugs are letters (both cases) and digits: five characters from the API and the home page (snu.to/x7Kp2), six from the console form (snu.to/aZ3k9Q).
| Use a random slug when | Use a custom slug when |
|---|---|
| People will only tap it: emails, chat messages, posts | People will type it: posters, slides, business cards, packaging |
| You create links in bulk from code | Someone will read it out: podcasts, talks, radio, phone calls |
| It's only ever a QR code, never shown as text | You'll read the report later and want to know which link is which |
| The link is a one-off you'll never look at again | Several placements share one destination and need separate counts |
A random slug is also the shortest option, which keeps a QR code small. It isn't secret, though: anyone who sees the link can open it. If a link must stay private, protect it with a password rather than counting on a slug nobody will guess.
7 rules for a good slug
- Lowercase only. Paths are case-sensitive;
snu.to/Menuis notsnu.to/menu. - Hyphens between words.
spring-menu, notspringmenuorspring_menu. - One to three real words, under about 15 characters. Every character is one more someone can mistype.
- No look-alike characters. Avoid mixing
0ando,1andl, orrnwheremwould also read. - One slug per placement. The poster and the Instagram bio each get their own link, so each gets its own count.
- Nothing private in it. Slugs are public: no customer names, email addresses or order numbers.
- Final before it's printed. A slug can't be changed, so check it, test it, then print.
The rest of this guide explains each rule and gives patterns to copy.
SendURL's slug rules
| Rule | Detail |
|---|---|
| Length | 1 to 32 characters |
| Characters | a–z, A–Z, 0–9, hyphen -, underscore _. No spaces, dots, slashes, accents or emoji |
| Case | Case-sensitive: Launch and launch are different slugs, and can belong to different people |
| Reserved | health, api, docs, robots.txt, favicon.ico, sitemap.xml, _next, in any letter case |
| Uniqueness | Across all of SendURL, not per account, because every link shares the snu.to domain |
| Changing it | Not possible after the link is created. The destination can change through the API |
| Deleting the link | Frees the slug for anyone. Disable a link instead if it was ever printed or shared |
When a slug breaks a rule, the API answers 400 validation_error with the reason in issues ("Slug must be 1-32 characters: letters, digits, '-' or '_'", or "That slug is reserved"). A slug someone already has is 409 slug_taken: "That slug is already taken — try another." The Create a link reference lists every field, and custom and random slugs covers the same rules in the console.
Case sensitivity, explained
The standard for URLs (RFC 3986) says the scheme and host "are case-insensitive", while "the other generic syntax components are assumed to be case-sensitive" (section 6.2.2.1). So SNU.TO/menu and snu.to/menu are the same address, but snu.to/Menu is a different one. Google treats paths the same way: it "treats both /APPLE and /apple as distinct URLs" (URL structure, updated 10 December 2025).
On SendURL that has two practical effects:
- A reader who types
snu.to/Autumn-Salefrom a poster when the link isautumn-salegets the "Link not found" page, and you never see the attempt. - Someone else can create
snu.to/Autumn-Saleas their own link. Your visitor who types the capitals lands on their page.
Lowercase removes both problems: there is only one way to type it. Mixed-case random slugs are fine for links people tap, because nobody types them.
Avoid look-alike characters
Some characters are hard to tell apart in print, in small type, or in a font you didn't pick. Crockford's Base32, a scheme designed for codes people copy by hand, leaves out I and L because they "can be confused with 1" and O because it "can be confused with 0" (Crockford Base32).
| Looks like | Example to avoid | Better |
|---|---|---|
0 and o, O | snu.to/2o20-promo | snu.to/promo-2020 |
1, l and I | snu.to/l1nks | snu.to/links |
rn and m | snu.to/modern-barn in a narrow font | test it in the print font |
5 and S, 2 and Z, 8 and B | snu.to/S5-offer | snu.to/summer-offer |
vv and w | snu.to/vvine | snu.to/wine |
- and _ | snu.to/spring_menu (the underscore vanishes when the link is underlined) | snu.to/spring-menu |
Lowercase-only removes the capitals (I, O, S, Z, B) from the problem. The rest you catch by reading the slug in the font it will be printed in.
Slugs people will type or hear
A link on a poster, a slide or in a podcast has to survive being read, remembered for a few seconds and typed on a phone. Some habits that help:
- Say it out loud before you pick it. "snu dot to slash e-p forty-two" works. "snu dot to slash e-p underscore four two dash notes" doesn't.
- Digits or words, not both for the same number.
ep42is fine; avoidfour-epnext toep4in the same show. - Avoid homophones.
2,toandtoo, or4andfor, invite the wrong one.deal-for-youheard on a podcast could be typed several ways. - Hyphens are "dash" to most listeners. If a slug needs more than two dashes, it's probably too long to say.
- Show it as text. Under every QR code, print the link itself (
snu.to/menu-window) for people who'd rather type it, and so the code clearly says where it goes.
For QR codes there's a size bonus too: slugs of 1 to 9 characters keep a SendURL code at 25×25 modules, and 10 to 25 characters at 29×29 (QR code size for print has the numbers).
Readable slugs and trust
People hesitate over short links because the link hides where it goes, and phishers use exactly that. The US Federal Trade Commission's advice is to "inspect the URL before you open it" when a QR code turns up somewhere unexpected (FTC, 6 December 2023).
A slug can't prove anything, but it can avoid looking wrong:
- Match the context.
snu.to/menu-tableon a table card reads as part of the card.snu.to/x7Kp2on the same card reads as nothing. - Avoid phishing words.
login,verify,account,secure,passwordandupdatein a slug are the vocabulary of scam messages. Your link may be honest; it will still look like the other kind. - Never name another company. A slug like
paypal-refundorbank-alertis how abuse looks, and links reported through the abuse form can be taken down.
What a slug can't change: the domain is snu.to, not yours. SendURL has no custom domains and no link preview page, so the slug and the text around the link are what tell people it's yours. Short link safety covers the other side, checking a link before you open it.
The "branded links get more clicks" figure
You'll see figures such as "39% more clicks" quoted for branded links. They come from vendors' marketing pages with no published method, so we don't use them. The research that exists is about search results: a 2007 Microsoft Research study found that features of a result's caption, including the length of the URL shown, "can significantly influence users' Web search behavior" (Clarke et al., SIGIR 2007). That's search results, not short links, and it gives no percentage for them. Pick readable slugs because people have to read, type and trust them, not because of a number.
A naming pattern that scales
For campaigns, one pattern covers almost everything:
<campaign>-<channel>[-<placement or variant>]Campaign first, so the links of one campaign sit together when you sort or search your links. Channel second, placement or variant last. Keep each part to one or two words.
| Campaign type | Example slugs |
|---|---|
| Product launch | aurora-launch-ig-bio, aurora-launch-email, aurora-launch-li, aurora-launch-poster |
| Seasonal sale | autumn-sale-ig-bio, autumn-sale-story-oct14, autumn-sale-sms, autumn-sale-window |
| Newsletter | news-2026-10, news-2026-10-cta, news-2026-10-footer |
| Podcast | tsp-ep42, tsp-ep42-notes, tsp-ep42-sponsor (a show prefix, because ep42 alone is likely taken) |
| Conference or event | devcon-booth, devcon-slides, devcon-badge, devcon-raffle |
| Restaurant or shop | menu-window, menu-table, menu-bag, menu-receipt |
| Print runs | flyer-oct-a5, flyer-nov-a5, box-insert-2026 |
| Creators and affiliates | autumn-sale-priya, autumn-sale-tom, one per creator |
| Message tests | autumn-a, autumn-b (see A/B testing with short links) |
| Job applications | cv-acme, cv-globex, one per application |
| Support and docs | setup-guide, returns, warranty-form |
| Webinars | webinar-nov-signup, webinar-nov-replay |
Some notes on the details:
- Length. Campaign slugs run past 15 characters, and that's fine for links people only tap. Keep the ones people type (posters, slides, podcasts) short.
- Dates.
1014reads as 14 October in some countries and nonsense in others. Useoct14, or2026-10for months. - Channels. Pick one short code per channel and keep it:
ig,tt,li,yt,x,email,sms,qr,poster. Write the list down. - Placements beat channels. "Instagram" is too coarse when you have five bio links and daily Stories:
ig-bio,ig-story-oct14,ig-dm. - People. A link per person (
cv-acme) tells you a click happened, not who clicked, and in the EU tracking an individual is processing personal data. If you track per person, say so. Can you see who clicked your link? covers what a click does and doesn't show.
The slug is for humans and for reading your link report. If you also use Google Analytics, the UTM parameters on the destination carry the same information in GA4's format; a UTM naming convention explains how the two fit together. Don't put UTMs in the slug.
Taken, reserved and rejected slugs
Slugs are global on snu.to. Short, common words (sale, menu, promo, ep1) are the first to go, so expect a 409 slug_taken and plan for it:
- Add your name or brand.
acme-sale,marios-menu. - Add the year or season.
sale-2026,autumn-sale. - Add the placement.
menu-windowis far more likely to be free thanmenu, and more useful.
Reserved words are refused in any case (API, Docs, HEALTH), and anything outside A–Z a–z 0–9 - _ or longer than 32 characters is a 400. A random slug can, very rarely, collide with an existing one; sending the same request again gets a new one.
Never reuse a printed slug
A slug means one thing for as long as copies of it exist. Flyers stay on noticeboards for months, packaging for years, and screenshots forever.
- New campaign, new slug. Don't repoint
autumn-sale-2026at next spring's sale; old flyers would send people to an offer that never appeared on them. Createspring-sale-2027. - Same thing, new address: change the destination. If the menu page moves, change where the link points and every printed code follows.
- Over: expire or disable it. An expiry date shows "Link expired" from the moment the offer ends; disabling shows "Link not found" and keeps the slug yours.
- Never delete it. Deleting frees the slug, and anyone can register
snu.to/autumn-sale-2026and receive the scans from your flyers.
Create a custom short link with the API
The REST API is on every plan. Send slug in the body:
curl -X POST https://api.sendurl.to/api/v1/links \
-H "Authorization: Bearer $SENDURL_API_KEY" \
-H "Content-Type: application/json" \
-d '{"destinationUrl": "https://example.com/autumn-sale", "slug": "acme-autumn-sale-2026"}'{ "error": "slug_taken", "message": "That slug is already taken — try another." }In code, try a short list of candidates in order and stop at the first free one. Node 18 or later, no packages:
const API = "https://api.sendurl.to/api/v1";
async function createWithFirstFreeSlug(destinationUrl, slugs) {
for (const slug of slugs) {
const res = await fetch(`${API}/links`, {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.SENDURL_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({ destinationUrl, slug }),
});
if (res.status === 409) {
console.log(`${slug} is taken`);
continue;
}
// Read the status before parsing: a 429 from Cloudflare is HTML, not JSON.
if (!res.ok) throw new Error(`HTTP ${res.status}: ${await res.text()}`);
return res.json();
}
throw new Error("every candidate slug is taken");
}
const link = await createWithFirstFreeSlug("https://example.com/autumn-sale", [
"autumn-sale",
"acme-autumn-sale",
"acme-autumn-sale-2026",
]);
console.log(link.shortUrl);Check slugs before you create them
When a sheet of placements becomes a batch of links, a lint step catches the mistakes the API allows: capitals, underscores and look-alikes are all valid slugs. This Python check flags them:
import re
import sys
RESERVED = {"health", "api", "docs", "robots.txt", "favicon.ico", "sitemap.xml", "_next"}
WORDS_WITH_HYPHENS = re.compile(r"^[a-z0-9]+(?:-[a-z0-9]+)*$")
def problems(slug):
found = []
if not re.fullmatch(r"[A-Za-z0-9_-]{1,32}", slug) or slug.lower() in RESERVED:
found.append("SendURL will reject it")
if slug != slug.lower():
found.append("has capitals")
if not WORDS_WITH_HYPHENS.match(slug.lower()):
found.append("use single hyphens between words, no underscores")
for word in re.split(r"[-_]", slug.lower()): # look-alikes side by side in one word
if "0" in word and "o" in word:
found.append(f"'{word}' mixes 0 and o")
if "1" in word and re.search(r"[li]", word):
found.append(f"'{word}' mixes 1 with l or i")
if len(slug) > 15:
found.append(f"{len(slug)} characters; can it be shorter?")
return found
for slug in sys.argv[1:]:
print(f"{slug:24} {'; '.join(problems(slug)) or 'ok'}")menu-window ok
Spring_Menu has capitals; use single hyphens between words, no underscores
l1nks-2o20 'l1nks' mixes 1 with l or i; '2o20' mixes 0 and o
autumn-sale-ig-bio-oct14 24 characters; can it be shorter?Checklist
- Custom slug only where people type, hear or read it; random everywhere else
- Lowercase, hyphens, one to three words, under about 15 characters
- No
0/o,1/l/imixes; read in the print font - Said out loud once, if it'll be spoken
- Follows the pattern
<campaign>-<channel>[-<placement>], with your written list of channel codes - One slug per placement, creator or variant
- Nothing private: no names, emails or order numbers
- No phishing words, no other company's name
- Short link printed as text next to every QR code
- Created and tested before the print file is sent; it can't change afterwards
- Old campaigns expired or disabled, never deleted
Shorten a link on the home page to see a random slug without an account; custom slugs come with a free account.
Frequently asked questions
How long should a custom short link be?
As short as it can be while still saying what it is: one to three words, ideally under 15 characters. SendURL allows 1 to 32 characters. Slugs of 9 characters or fewer also keep the QR code at its smallest size.
Should I use hyphens or underscores in a slug?
Hyphens. They are easier to say, easier to see, and Google recommends them over underscores for separating words in URLs. An underscore also disappears when a link is shown underlined.
Can I change a short link's slug later?
Not on SendURL. The slug is fixed once the link exists, because printed QR codes and copies of the link depend on it. You can change where it points through the API, or create a new link and disable the old one.
Is a custom short link the same as a branded short link?
No. A branded short link usually means a short link on your own domain. SendURL doesn't offer custom domains: every link is on snu.to, and the custom part is the slug after the slash.
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