Here's how to use Astro server islands and Cloudflare geo headers to display a different price by region.
Demo: https://astro-geo.pages.dev
npm create astro@latest astro-geo
For this simple case, set 'Empty project'/'No Typescript'/'Install dependencies'/'Initialize a new git repository' options
npx astro add cloudflare
This will be default in Astro 5.0, but for now add the following to astro.config.mjs
export default defineConfig({
experimental: {
serverIslands: true,
},
});In the frontmatter, grab the Cloudflare cf-ipcountry header
---
const countryCode = Astro.request.headers.get("cf-ipcountry")
---
<h1>countryCode: {countryCode}</h1>- Vercel:
Astro.request.headers.get('X-Vercel-IP-Country') - AWS:
Astro.request.headers.get('cloudfront-viewer-country') - Netlify:
Astro.request.headers.get('x-country')(see the Netlify branch for a demo) - If there's one for Azure Static Web Apps, let us know!
Just add the server:defer attribute: <GeoLocation server:defer />
Publish your project to GitHub/Lab and crate a pages app from it via your Cloudflare dashboard
Once built, when you visit the app in your browser you should see countryCode: GB or whatever your country is.
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>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!


