DEV Community

Cover image for Why I Built Amazon Store (So I Don't Have to Pick a Country)
Dave Cross
Dave Cross

Posted on

Why I Built Amazon Store (So I Don't Have to Pick a Country)

I run a handful of small content sites — Perl School, Readabooker, Mercurial Albums, and a few others. They're all different niches, but they share one thing in common: they link to products on Amazon, and those links carry my associates tag.

If you've ever tried to do this properly, you already know the problem. Amazon isn't one store, it's dozens — amazon.com, amazon.co.uk, amazon.de, amazon.fr, amazon.co.jp, and so on — each with its own catalogue, its own currency, and its own associates program. A link to amazon.com is nearly useless to someone in Germany. It won't reliably resolve to the local listing, and even when it does, you don't get credited for the sale because you're not in the German associates program for that link.

So every site owner with an international audience ends up picking one of two bad options:

  1. Pick one store and eat the loss. Link everything to amazon.com, or amazon.co.uk, or wherever your own associates account lives, and accept that a chunk of your visitors will either not click through or will click through and generate no commission for you.
  2. Maintain a link for every store. I had a Perl program that would generate a button or a link for a given ASIN for every Amazon site I thought I needed to cover. This scales terribly once you're running more than one site; it looks horrible on the website; and it's exactly the kind of tedious, error-prone busywork I wanted off my plate.

I'd been switching between these options for years, mostly out of laziness, and it always bugged me. So earlier this year I finally sat down and — with some help from AI along the way — wrote Amazon Store, a small, dependency-free JavaScript library that solves this properly.

What it actually does

The idea is simple: instead of hardcoding a store into your Amazon link, you hardcode the product. You give the library an ASIN (the identifier every Amazon product has, and the one bit of data that's genuinely the same across every regional store), and optionally your associates tag, and it works out which store to send the visitor to at the moment they load the page.

It does this by looking at browser signals first — navigator.languages and the visitor's time zone give a pretty strong hint about where someone actually is, far more reliably than trying to guess from IP geolocation server-side. If those don't produce a confident answer, it falls back to the page's lang attribute, and then to the hostname's TLD. Once it's picked a store, it builds the correct link — right domain, right associates tag — and swaps it in.

Crucially, it does this as progressive enhancement. The markup you write is a normal, working link before any JavaScript runs. If JS is disabled, or the library fails to load, or a script blocker gets in the way, the link still points somewhere sensible — it just doesn't get the region-aware rewrite. Nothing breaks.

What it looks like in practice

You include the script (there's a CDN build, or you can npm install amazon-store and bundle it yourself):

<script src="https://cdn.davecross.co.uk/js/amazon-store/v1/amazon-store.min.js" defer></script>
Enter fullscreen mode Exit fullscreen mode

Then initialise it once the page is ready:

document.addEventListener('DOMContentLoaded', () => {
  AmazonStore.enhanceAll({ tag: 'your-associates-tag' });
});
Enter fullscreen mode Exit fullscreen mode

And your product links just need an ASIN:

<a class="btn btn-primary"
   data-amazon-asin="B0DJRYGFKM"
   data-amazon-text="Buy on Amazon"> </a>
Enter fullscreen mode Exit fullscreen mode

That's it. No per-region duplication, no spreadsheet of store-specific links to maintain across half a dozen sites. One ASIN, one tag, and the library figures out the rest. There's also a data-amazon-region attribute if you ever want to force a specific store, and a data-amazon-search attribute for cases where you'd rather link by search terms than a fixed ASIN — handy for affiliate links where you don't want to pin an exact listing.

If you'd rather let the visitor choose than have the library guess, there's also a store grid renderer (added in v1.1.0) that shows a "more stores" picker, so people can pick their own region explicitly instead of trusting the detection.

Help me find the edge cases

Region detection from browser signals is never going to be perfect, so I recently built a debug page that runs through exactly the same checks the library does, in the same order, and shows you which store it landed on and why.

That "why" matters more than you'd think. The most common mismatch I've seen so far: a customer in India gets routed to the US store, not because the detection is broken, but because their browser's language is set to plain en rather than en-IN — and en on its own isn't enough to distinguish India from the US, the UK, Australia, or anywhere else that lists English first. Without a page like this, that kind of thing is invisible; you'd just see a slightly lower conversion rate from a region and never know why.

The debug page runs its checks in the same priority order as the library — browser language, time zone, and so on — stopping at the first one that produces a confident match, so you can see precisely which signal decided the outcome. There's a button to copy the full diagnostic output, which is exactly what I'd want to read in a GitHub issue about a mismatch. If you've got a few minutes and an unusual locale setup (a VPN, a second language set as primary, a less common Accept-Language combination), I'd genuinely appreciate you trying it and telling me what it gets wrong — the more edge cases that surface now, the better the detection gets for everyone.

Why this might be useful to you

If you're maintaining even two or three sites with Amazon links, and you've got any kind of international audience, you've probably hit this exact problem — either quietly losing commission on visitors from other countries or drowning in region-specific link management. That's really the whole reason this exists: I wanted to write my HTML once, per product, and never think about it again.

It's MIT-licensed, has no dependencies, and ships as both UMD and ESM builds. You can also self-host it rather than pulling from the CDN, with SRI hashes provided if you want the integrity guarantees without giving up control of where the script is served from.

It's still early days for the project, so if you try it on your own site and hit something odd — or have a store/region edge case it doesn't handle well — I'd genuinely like to hear about it. Issues and PRs on GitHub are welcome.

Top comments (0)