🔳 Bulk QR Codes + UTM Links

Build a whole campaign of tagged links at once, then download every one as a QR code PNG plus a ready to open links.csv, in a single ZIP. Free, no signup, up to 500 links per pack, and nothing is uploaded.

Step 1
Where the links point
If the page already has a query string or a #section, both are kept. Any UTM value already on it is replaced by yours.

Presets are stored in this browser only. They are not sent anywhere and they will not follow you to another device.
Step 2
Build the rows
Campaign matrix
Paste or CSV
Where the visit comes from.
How it gets to you.
Every campaign is combined with every source, medium, content and term.
Drop a .csv file here
or click to choose, or paste it in the box below
Recognised headers: url, source, medium, campaign, content, term, id, label. Leave the url column out and the destination from Step 1 is used for every row. If none of those headers are found, every line is read as one complete link instead. Up to 500 rows per pack, so split a bigger file and run it twice.
Cleaning is applied to utm_source, utm_medium, utm_campaign, utm_term and utm_id only. Your page address, its path and utm_content are left exactly as typed, because funnel paths, ad IDs and hashes are case sensitive. Any value containing { } or % is passed through untouched, so ad platform macros such as {{ad.id}} and {keyword} keep working.

Step 3
Check the links
LabelFinal link

Step 4
QR codes and download
code / behind
That border is part of the code, not padding. Cropping it is the most common reason a printed QR code will not scan.
Two honest limits before you print anything.
These are static QR codes: the link is baked into the image, so it cannot be pointed somewhere else after the flyers come back from the printer, and there is no scan counter. The UTM values in your analytics are how you count them instead.
The ZIP also holds crm-mapping.csv, a reference sheet of which UTM parameter belongs in which GoHighLevel field, including the one that catches people out: GoHighLevel stores utm_term as utmKeyword. That sheet is a note for whoever wires up your form. It does not connect anything by itself, your landing page and form still have to capture the values, and contacts created through an API arrive without them.

🎬 Plus a single QR generator, batch watermarking, PDF signing & 250+ more free toolsOpen Castwright

The batch is the hard part, not the builder

Google's own Campaign URL Builder is free and perfectly good for one link. The trouble starts the moment a campaign has four sources and three placements, because now you are hand typing twelve links and a single stray capital letter splits one campaign into two rows in your report. This page expands the whole grid in one pass, cleans every value the same way, and hands back a spreadsheet plus a QR code for each link.

What the QR pack is really for

Print does not carry a referrer. A flyer, a table tent, a yard sign, a vehicle wrap, a packaging insert and a trade show banner all arrive in your analytics as direct traffic unless each one carries its own tagged link. Give every printed piece a different utm_content value and you can finally see which piece paid for itself. Making those codes one at a time is exactly where most free QR sites stop and start asking for a card.

The naming rules this bakes in

utm_source is where the visit came from, such as facebook, google or flyer. utm_medium is how it travelled, such as cpc, email, social or qr. utm_campaign is the thing you are running, such as spring-sale-2026. Keep those three lowercase and hyphenated and your reporting stays in one clean row per campaign instead of four near identical ones. utm_content is deliberately left exactly as you typed it, because ad IDs, hashes and merge macros are case sensitive and lowercasing them quietly breaks the join.

Where a tagged link stops

A UTM link only carries values in its address. Something at the other end still has to read them: your analytics does it automatically, a CRM only does it if the landing page and form are wired for it. That is worth knowing before you print two thousand flyers. Test one link end to end, confirm the values land where you expect, then run the batch.

Everything runs on your machine

The links are assembled and the QR codes are drawn in your own browser. No destination URL, no client name and no campaign is sent to a server, so you can build packs for client work without a privacy conversation. Saved presets live in this browser's local storage and nowhere else.