Create a new Astro project
npm create astro@latest astro-geo
For this simple case, set the Astro options as follows:
Empty project
No Typescript
Install dependencies
Initialize a new git repository
Add the Cloudflare adapter
npx astro add cloudflare
Enable server islands
This will be on by default in Astro 5.0, but for now add the following to astro.config.mjs
export default defineConfig({
experimental: {
serverIslands: true,
},
});
Add a GeoLocation component
In the frontmatter, grab the Cloudflare cf-ipcountry
header 1
---
const countryCode = Astro.request.headers.get("cf-ipcountry")
---
<h1>countryCode: {countryCode}</h1>
Add the component to index.astro as a server island
Just add the server:defer
attribute: <GeoLocation server:defer />
. Read more about Astro server islands
Create a new Cloudflare pages app
Publish your project to GitHub/Lab and create a Pages app from it via your Cloudflare dashboard
Check it’s working
Once built, when you visit the app in your browser you should see countryCode: GB
or whatever your country is
Customise per region
Let’s show £ if you’re in the UK, € if you’re in the EU and default to $ in the rest of the world
---
const countryCode = Astro.request.headers.get("cf-ipcountry")
const euCodes = ["AT", "BE", "BG", "HR", "CY", "CZ", "DK", "EE", "FI", "FR", "DE", "GR", "HU", "IE", "IT", "LV", "LT", "LU", "MT", "NL", "PL", "PT", "RO", "SK", "SI", "ES", "SE"];
// Default USD
let geolocatedSymbol = "$";
let geolocatedPrice = 19.99;
// If GB
if (countryCode === "GB") {
geolocatedSymbol = "£";
geolocatedPrice = 29.99;
}
// If in EU
else if (euCodes.includes(countryCode)) {
geolocatedSymbol = "€";
geolocatedPrice = 39.99;
}
---
<h2>Price: {geolocatedSymbol+geolocatedPrice}</h2>
Done!
Push your code up and check the build in your browser. If you have a vpn, try switching between US/UK/EU servers and reloading.
View live demo: astro-geo.pages.dev
If you need an Astro website, do get in touch!
Footnotes
-
It has been pointed out that we can just use
Astro.request.headers.get("cf-ipcountry")
rather the more cumbersomeObject.fromEntries(Astro.request.headers)?.["cf-ipcountry"]
we previously used, updated with thanks! ↩