How to add a QR code to website — three honest options

Three real ways to add a QR code to website — static image, JS library, or hosted on a short-link domain. The trade-offs on print, edits, and analytics.

May 18, 2026 17 min read Linked.Codes
How to add a QR code to website — three honest options

There are exactly three honest ways to add a QR code to your website, and almost every tutorial out there hand-waves the differences between them. The first is to drop a static PNG into an <img> tag — cheapest, fastest, zero analytics, and the URL inside the code is welded shut the moment you save the file. The second is to render the QR client-side with a JavaScript library, which feels modern, costs more in render time, and still gives you no per-scan tracking. The third is to host the QR on a short-link platform behind a domain you control, embed that image, and pick up editable destinations plus scan analytics in exchange for one DNS record and a small monthly cost.

Which one is right for your site depends on whether you'll ever want to change where the code points, whether you need to know how many people scanned it, and whether the code ever makes it onto something printed. This post walks through all three approaches the way they actually behave once they're live — code, trade-offs, the part where it breaks for a real business — and ends with a picker that tells you which one to use based on five honest questions about your situation.

The three approaches, head to head

Before any code, here's the shape of the decision. Every "how to add a QR code to your website" tutorial collapses into one of these three buckets. Most pretend their bucket is the only one worth showing.

Three approaches to adding a QR code to a website, compared on cost, edits, analytics, and print fit Three approaches — what each one costs you APPROACH STATIC IMAGE JS LIBRARY HOSTED QR Setup cost free free platform fee Edit destination later no redeploy site yes — one click Scan analytics no no per-scan Page weight ~3 KB 25-60 KB JS ~3 KB Render speed instant ~80-200 ms instant Survives print run stuck on first URL stuck on first URL yes — repoint later Team handoff dev only dev only marketing dashboard Best for stable URLs user-typed input marketing surfaces
The three honest approaches, scored on the things that actually matter once the code is live.

Across the rest of the post, each approach gets a real recommendation — the code, the right use case, the failure mode you should plan for, and the moment it stops being the right answer.

Approach 1 — Drop a static PNG into an <img> tag

This is the approach 80% of online tutorials describe. You open a free QR generator, paste the destination URL, click download, save the PNG to your repo, and embed it like any other image.

<img src="/img/scan-to-buy.png" alt="Scan to visit our shop" width="160" height="160">

That's it. The QR code lives in your /img folder, the destination URL is baked into the pixels, and the moment a phone decodes the pattern it goes straight to whatever URL you generated against. No JavaScript, no server hop, no third party in the loop after the image loads.

What's good about it: the page weight is whatever the PNG weighs — usually 2 to 4 KB for a typical 300×300 px QR. It renders the instant the browser paints the image. There's no third-party dependency to break, and if you ever take your site down the QR image goes down with it but the file itself is still scannable if someone saved a copy. For a homepage QR that points to your single most important page (your shop, your booking page, your newsletter), and you're confident that URL will never change, this is genuinely fine.

What breaks it: the URL is welded into the pattern. Move your shop from /shop to /store, change domains, restructure your URL scheme, run a seasonal campaign that needs the QR to point somewhere different for two weeks — every one of these means regenerating a new PNG, re-uploading it, and re-deploying the site. You also have zero idea how many people are actually scanning the code. Was the QR worth the homepage real estate? You can't say. The destination's analytics will see referral traffic but a phone-camera scan rarely passes a useful referrer, and even if it did, scans that abandon before loading the page never show up at all.

The other quiet trap is print. Static images on your website often get reused offline — your QR ends up on a postcard, an event flyer, the back of a packaging insert. The version stuck on the printed flyer encodes the original URL. Six months later you change your shop URL and the website's QR can be regenerated in 30 seconds; the printed flyers become coasters. This is the failure mode laid out in static vs dynamic QR codes — once the pixel pattern leaves your control, the URL inside it is frozen.

When the static-image approach is the right answer: the QR points to a fact-of-the-world URL that won't change for at least three years (your homepage, an evergreen landing page, a "scan to connect to our WiFi" code on a coffee-shop wall), and the QR exists only on the website, never on something printed.

Approach 2 — Render the QR client-side with a JavaScript library

The second tutorial pattern: pull in a QR library like qrcode.js or qr-code-styling, give it a <div> to render into, and let the browser draw the QR on every page load.

<div id="qr"></div>
<script src="https://cdn.example.com/qrcode.min.js"></script>
<script>
  new QRCode(document.getElementById("qr"), {
    text: window.location.origin + "/shop",
    width: 200,
    height: 200
  });
</script>

Why people reach for this: the QR can encode dynamic content — the current page URL, a string the visitor typed into a form, a session-specific token. For "scan to continue on your phone" flows, where the QR has to encode something the server didn't know at build time, this is genuinely useful. For "share this URL via QR" widgets on every blog post, where the encoded text changes per-page, the JS approach lets you avoid generating a thousand individual PNG files at build time.

Why it costs more than it looks like: the library itself is 25 to 60 KB minified, and most of them ship as a dependency you have to keep updated. The render isn't instant — there's a measurable delay (somewhere between 80 and 200 milliseconds on a mid-range phone) between the page loading and the QR appearing, because the canvas has to be drawn pixel by pixel from a Reed-Solomon encoding routine in JavaScript. If your site cares about Largest Contentful Paint, the QR is now in the critical path.

The bigger problem is that you still get no analytics. The library renders a static QR on the fly; the encoded URL is whatever you passed to the library, and a phone that scans it goes straight to that URL with no redirect server in the middle. You've moved the rendering step from build time to runtime, but the QR itself is just as static-feeling as approach 1 — same encoded URL, same lack of scan tracking, same inability to repoint after print.

And there's a subtle reliability dimension. The QR appears in the DOM only after JavaScript executes. If your visitor has JS disabled, slow, blocked by a content-blocker, or fails to load from a CDN that's having a bad day, the QR is just missing. A static <img> tag survives all four of those.

When the JS-library approach is the right answer: the QR has to encode content that depends on runtime state (current URL, form input, a token generated for this session), and you can live without analytics. For everything else, it's the worst of both worlds — heavier than a static image, no editable destination, no per-scan tracking.

The third approach is what every marketing-grade QR on the web actually does. You pick a short-link platform, you connect a subdomain you control (link.yourbrand.com, go.yourbrand.com, or a separate short domain like yourbrnd.co), you generate a QR through the platform's dashboard, you embed the resulting image on your site, and the encoded URL inside the QR is a short link that 302-redirects through the platform to wherever you tell it to.

<img src="https://link.yourbrand.com/q/spring.png" alt="Scan to view the spring campaign" width="160" height="160">

The image is still a regular PNG. The page weight is still ~3 KB. The render is still instant. The thing that changes is where the encoded URL points: not directly at your shop, but at link.yourbrand.com/k/spring, which the platform then redirects.

What you get in exchange for the setup cost:

  • Editable destination. Change where link.yourbrand.com/k/spring points in the dashboard, every QR in the wild — on the website, on the flyer, in the conference handout — starts going to the new URL within the next scan. No reprints, no redeploy.
  • Per-scan analytics. Every scan is a request to the redirect server. The platform logs the timestamp, the country, the device class, the referrer where available. You can finally answer "did the QR work?" with numbers.
  • The QR survives going off-screen. A scan analytics dashboard sees the same code whether it was scanned from your homepage, a printed sticker on packaging, or a screenshot somebody shared in a Slack channel. The QR's encoded URL is the same in all three places, so one platform sees the whole picture.
  • Team handoff. A marketing teammate can change the destination in the dashboard without touching the website's HTML. The web developer doesn't get a Slack message every time the campaign URL needs to move.
  • Brand on the encoded URL. When a phone offers the URL preview before opening it ("Open link.yourbrand.com/k/spring?"), the visitor sees your domain. With approach 1 they'd see whatever long URL you encoded.

What it costs: the platform fee (usually a monthly subscription or the lifetime tier one-time payment), the 30-minute DNS setup to connect your subdomain to the redirect server, and a hard dependency on the platform staying alive. If the redirect host disappears and you haven't picked one that lets you migrate, every QR using the short link goes dark. The mitigation is to use a platform that runs on a domain you control via DNS, so if you ever need to switch backends, you point the DNS record at a different redirect server and the URL inside the printed QR codes keeps resolving. That's the level-2 architecture the owning your link infrastructure post breaks down in detail.

When approach 3 is the right answer: anywhere the QR exists on a marketing surface, anywhere it might end up in print, anywhere you actually want to know if it's working, anywhere a non-developer might need to change where it points. That's most of the QR codes a business produces.

What happens at scan time for each of the three approaches Scan-time flow — what each approach actually does 1. Static image Phone scans PNG URL decoded (welded into pixels) Destination opens No log, no edits 2. JS-rendered Phone scans canvas URL decoded (same — JS only renders it) Destination opens No log, no edits 3. Hosted QR — short link Phone scans PNG Short link decoded link.brand.com/k/spring 302 redirect → dest Logged · editable
Static and JS-rendered codes both encode the destination directly. The hosted-QR path adds one redirect — invisible to the user, decisive for the business owner.

Anatomy of a hosted QR on a custom domain

The hosted-QR approach is what most "how to add a QR code to your website" tutorials skip entirely, partly because it's slightly more setup than dropping in an <img> tag and partly because every QR generator that doesn't sell hosting has an incentive to pretend the static option is just as good.

Here's what the moving pieces look like when you wire it up properly. The QR image lives on the platform, the encoded URL inside it lives on your domain, the redirect happens on the platform's server, and the destination is whatever URL you've set in the dashboard at any given moment.

Anatomy of a hosted QR with a custom short-link domain — image, encoded URL, redirect, destination Anatomy of a hosted QR — four moving pieces 1. The image Lives on the platform CDN Embedded via <img> tag 2. Encoded URL link.yourbrand.com /k/spring on a domain YOU control 3. Redirect rule spring → /campaigns/2026 Editable in the dashboard Every scan is logged 4. Destination yourbrand.com/campaigns/2026 Can change without reprinting
The four pieces of a hosted QR on a custom domain. Each one can change without disturbing the others.

The piece most people skip when they first build this is point two — the encoded URL lives on a domain you control, not on the platform's domain. That detail is what insures you against the platform vanishing in three years. If the redirect host disappears, you point your DNS record at a different short-link platform that can re-host the slug-to-destination map, and every printed QR keeps resolving. The DNS escape hatch is the single most underrated property of the hosted approach. The step-by-step DNS work is covered in setting up a custom short-link domain — it's a one-record CNAME on every modern registrar.

Putting the QR on the actual page

Once the QR exists on the platform, embedding it on the website is identical to embedding any other image. Three small details worth getting right.

Width and height attributes. Always set them — browsers reserve the layout slot before the image downloads, which prevents layout shift. A QR with a missing height attribute is one of the most common Cumulative Layout Shift offenders on small-business websites.

<img src="https://link.yourbrand.com/q/spring.png"
     alt="Scan to view the spring campaign"
     width="180" height="180" loading="lazy">

Alt text that describes the action, not the image. "Scan to view the spring campaign" is useful. "QR code" is not. Screen readers read alt text aloud, and a visitor who can't see the code can't scan it from a phone camera — they need the destination URL spelled out elsewhere on the page or a direct link. Add a link next to every QR for accessibility:

<a href="https://link.yourbrand.com/k/spring">Or open the campaign directly</a>

The size on screen. A QR rendered at less than about 120 px square starts failing reliably on mid-range phone cameras held at a normal scanning distance. 160 to 220 px is the sweet spot for on-screen QR codes. Smaller is fine if you genuinely expect visitors to put their phones right against the screen; bigger wastes pixels. The full size-vs-scan-rate trade-off is in QR code not scanning — six fixes, worth a skim before you ship a code at 80 px because it looked tidier in the design mock.

Which approach is right for your site?

Five honest questions. Each answer scores points; the picker totals them and tells you which of the three approaches your situation is actually pointing at.

Which approach fits your site?

1. Will you ever want to change where the QR points after it ships?
2. Do you need to know how many people scanned the code?
3. Will the QR also appear in print — flyers, packaging, signage, business cards?
4. Does the QR encode something specific to the visitor (current page URL, form input, session token)?
5. Who needs to be able to change the destination later?
Recommended approach
Answer the questions above
Each answer adds a point to one of the three approaches. Pick the option closest to your situation — the picker totals the points and tells you which approach fits.

The picker leans toward the hosted approach if you answer yes to any of the print, edit, or analytics questions — because once those are real requirements, the other two approaches stop being honest options.

A QR code on a website that you can never edit and never measure is a magic trick, not a marketing surface.

The decision in one sentence per use case

A few common scenarios, mapped to the right approach so you don't have to think about it twice.

Homepage QR pointing to your shop or booking page. Hosted QR on a custom domain. The URL behind it will change at least once in the lifetime of your business, and you'll want to know if anyone is scanning it.

WiFi password QR in a café or office. Static PNG. The password is a fact about the network; encoding it directly in a printed sign is the right answer. There's no destination to repoint.

"Scan this to continue on your phone" QR on a desktop checkout flow. JS-rendered. The QR has to encode a session-specific token that the server only knows at runtime. Static won't work, hosted is overkill, JS is the fit.

QR on a blog post that points to the post's own URL ("share this article via QR"). JS-rendered. The encoded URL changes per page, you don't need analytics on it, and you don't want to pre-generate a thousand PNGs at build time.

QR on a printable PDF guide that customers will save and re-open offline. Hosted QR on your domain. The PDF outlives the URL inside it; without the hosted indirection you're committing to whatever destination URL exists today, forever. The mirror-image case — a printed QR that opens a PDF on whoever scans it — has its own set of host, file-size, and first-byte concerns, all in the breakdown on PDF QR codes.

QR in your email signature. Hosted QR. Email signatures are essentially print — you can't recall them, the recipient might save them, and any URL inside them needs to be repointable when your link strategy changes. The post on branded short links and the domain that matters covers why the domain on the encoded URL is doing as much work as the QR itself.

QR on packaging for a product with a one-year shelf life. Hosted QR, with a clearly-staged repoint path for when the URL needs to change.

For the docs version of how the dashboard wires this together end-to-end on the platform side, QR codes — platform docs walks through it. If you'd rather skip straight to designing a code, the free QR code generator lets you pick the style and download the PNG without an account — the right starting point for the static-image approach and a useful sanity-check for the hosted version too.

The mistake most "add a QR code to your website" tutorials make

If you've read more than three tutorials on this, you've noticed the pattern: most of them describe approach 1 in detail, sometimes show approach 2 with a code snippet, and treat approach 3 as a vague mention of "for advanced use cases, consider a dedicated platform". The result is that small businesses keep shipping static QR codes for things that very much want to be editable and trackable, find out twelve months later that they have no idea whether the QR worked, and feel like they've done something wrong rather than picked the wrong tool.

The honest framing is the inverse: approach 3 is the default for marketing-grade QR codes on the web, and approaches 1 and 2 are special-case answers for genuinely-fixed URLs and runtime-specific encoding. Most tutorials get this backwards because the people writing them are usually showing you what's free and easy, not what's right.

That doesn't mean every QR needs the hosted approach. The WiFi-in-the-café code is fine static. The session-token "scan to continue" code needs JavaScript. But the QR on your homepage that points to your most important page? That's a hosted QR. The QR in your email signature? Hosted. The QR you're putting on packaging? Hosted with both hands.

Sourcesshow citations
Can I just use a free QR generator and embed the image?

Yes — that's approach 1 in this post. It works perfectly for QR codes whose destination URL will never change and that you don't need scan counts for. For anything you'd want to edit later, or that ends up in print, the hosted approach pays back the setup cost quickly.

How do I add a QR code to my website without using JavaScript?

Approach 1 (static PNG in an <img> tag) and approach 3 (hosted QR image embedded the same way) both work without any client-side JS. The QR is just an image. Only approach 2 — rendering the code client-side with a library — requires JavaScript on the page.

Do scan analytics work if the visitor scans the QR from a screenshot or photo of my website?

With approach 3, yes. The encoded URL is the same short link whether it was scanned from your live site, a screenshot, a printed copy, or someone's Slack message. The redirect server sees every scan regardless of how the QR pattern reached the camera.

What if my QR has to encode a per-visitor URL, like a session token?

Approach 2 (JavaScript-rendered) is the fit. The library can encode whatever string you compute at runtime — including a token that's unique per page load. You give up scan analytics in exchange, but for "scan to continue on your phone" flows that's usually the right trade.

Will a hosted QR slow my site down?

No more than any other image. The QR is a PNG hosted on the platform's CDN, embedded in an <img> tag with width and height attributes. Page-weight cost is the same as a 3 KB image. The redirect only runs when somebody scans the code, not when the page loads.

What happens if my hosted-QR platform shuts down?

If the QR encodes a URL on a domain you control via DNS, you point that DNS record at a replacement platform and the printed QR codes keep resolving. If it encodes the platform's own domain, every QR in the wild breaks. This is why approach 3 is only worth it on a platform that supports custom domains — the DNS escape hatch is the whole point.

Can I move from approach 1 to approach 3 later without breaking anything?

On the website, yes — swap the <img src=...> to the new hosted URL and you're done. Printed copies of the old QR keep encoding the old URL, so you'd need a server-side redirect at the original destination to bridge them. That's a workaround, not a true migration — easier to start with approach 3 anywhere print is in scope.

Try it on your own domain

Branded short links and dynamic QR codes, on your subdomain or your own domain. One-time purchase, no per-click fees.