Geolocation at the Edge: Lessons from Real A/B Tests and Experiments (Fastly, Vercel, Cloudflare & More)

Overview
Modern CDNs and edge platforms (Fastly, Vercel, Cloudflare, Akamai, etc.) all expose some kind of geolocation data for each request: country, region, sometimes city and rough coordinates.
Used properly, this data is enough to:
- Run location-aware A/B tests
- Personalise hero copy, CTAs, and pricing
- Pre-fill forms with country/region
- Improve maps and "near you" logic without asking for browser geolocation
This article focuses on practical, production-level lessons from using geo headers and edge APIs across different providers, with examples for:
- Fastly – geo headers
- Vercel – request.geo & middleware
- Cloudflare – CF-IPCountry and request properties
- Generic curl/debug examples you can adapt anywhere
No provider marketing. Just what actually works in A/B tests and experiments.
1. What "Edge Geolocation" Actually Is
Almost all CDNs do the same thing under the hood:
- Take the visitor's IP address
- Look it up in a GeoIP database (MaxMind-style)
- Attach the result to the request as:
- HTTP headers
- Environment variables
- Edge runtime APIs (request.geo, request.cf, etc.)
This happens before your app code runs, which is why it works even on cached pages.
Typical data you get
Depending on provider, you'll see some or all of:
- Country – always present (GB, US, DE, etc.)
- Region / State / Province
- City – often present but not always reliable
- Latitude / Longitude – approximate
- Connection type (broadband / mobile / corporate)
2. Accuracy in Real Life
Across providers, the patterns are extremely similar:
Country-level
- Accuracy: ~99%
- Safe for:
- Language variants
- Pricing
- Legal/compliance banners
- Country-specific pages
Region / State
- Accuracy: ~85–95%
- Good for:
- US states
- UK nations/regions
- Canadian provinces
- Broad targeting (e.g. "Southern California" vs "New York")
City-level
- Accuracy: 40–70% depending on:
- Mobile vs fixed broadband
- VPN usage
- Carrier routing
- Do not rely on this for anything critical (distance, "near you", etc.)
Mobile connections
- Biggest source of error across all providers
- IPs often terminate in:
- Another city
- Another region
- Occasionally another country (roaming, central hubs)
Conclusion: treat mobile geolocation as "approximate region", not city precision.
3. Fastly Geolocation – Headers & Usage
Fastly exposes geo data via response headers (and optionally via a JS object if configured).
Common headers:
Fastly-Client-CountryFastly-Client-RegionFastly-Client-CityFastly-Client-LatitudeFastly-Client-Longitude
Check with curl
curl -I https://yourdomain.com | grep -i fastly
You'll typically see something like:
Fastly-Client-Country: GB
Fastly-Client-Region: ENG
Fastly-Client-City: London
Fastly-Client-Latitude: 51.500
Fastly-Client-Longitude: -0.100
Client-side fallback (HEAD request)
If you don't have window.FastlyGeo, you can still use headers:
async function getFastlyGeo() {
var resp = await fetch(window.location.href, { method: "HEAD" });
return {
country: resp.headers.get("Fastly-Client-Country"),
region: resp.headers.get("Fastly-Client-Region"),
city: resp.headers.get("Fastly-Client-City"),
latitude: resp.headers.get("Fastly-Client-Latitude"),
longitude: resp.headers.get("Fastly-Client-Longitude")
};
}
getFastlyGeo().then(console.log);
This pattern works with any CDN that exposes geo via headers.
4. Vercel Geolocation – request.geo in Edge Middleware
If you're on Vercel (Next.js, Edge Runtime), you don't see headers like Fastly-Client-Country.
Instead, geolocation is exposed via request.geo in middleware or edge functions.
Example: Next.js middleware
import { NextResponse } from "next/server";
import type { NextRequest } from "next/server";
export function middleware(req: NextRequest) {
const geo = req.geo || {};
const country = geo.country; // e.g. "GB"
const region = geo.region; // e.g. "England"
const city = geo.city; // e.g. "London"
// Simple experiment bucket based on country
if (country === "US") {
// set a cookie, choose variant, etc.
}
return NextResponse.next();
}
What you typically get in req.geo
countryregioncitylatitudelongitude
The accuracy profile is the same as other providers: great for country/region, less reliable for city, particularly on mobile.
5. Cloudflare Geolocation – CF-IPCountry and request.cf
Cloudflare exposes geo info in two main ways.
5.1. HTTP header: CF-IPCountry
Check with curl:
curl -I https://yourdomain.com | grep -i cf-ipcountry
Example:
CF-IPCountry: US
5.2. Worker API: request.cf
In a Cloudflare Worker:
export default {
async fetch(request, env, ctx) {
const cf = request.cf || {};
const country = cf.country; // "US"
const region = cf.region; // "CA"
const city = cf.city; // "San Francisco"
const latitude = cf.latitude; // "37.7749"
const longitude = cf.longitude; // "-122.4194"
// Use this to choose variant, personalise, etc.
return new Response(`Hello from ${country || "unknown"}`);
}
};
Again: country is rock solid, region is good, city is approximate.
6. Common Use Cases Across Platforms
Regardless of whether you're on Fastly, Vercel, Cloudflare or something else, the patterns are the same.
6.1. Regional landing pages
Examples:
- "AI consulting services in United Kingdom"
- "Solar incentives in California"
- "Healthcare clinics near Ontario"
Implementation patterns:
- Use country/region to:
- Select content variant
- Switch hero copy
- Swap testimonials
- Change currency or legal notes
6.2. Form prefill and validation
Use edge geo to:
- Default country field
- Suggest region/state field
- Route form submissions to different backends
Example (generic):
function applyGeoDefaults(geo) {
var countrySelect = document.querySelector("#country");
var regionSelect = document.querySelector("#region");
if (countrySelect && geo.country) {
countrySelect.value = geo.country;
}
if (regionSelect && geo.region) {
regionSelect.value = geo.region;
}
}
6.3. A/B tests by geography
Examples:
- Variant A for US/UK, Variant B for EU
- Different copy for "North America" vs "Europe"
- Different incentives by region
Implementation:
- Server-side or edge middleware picks variant based on country / region
- Set a cookie with variant ID
- Client-side library (Optimizely, custom JS, etc.) reads that cookie
6.4. Google Maps and local suggestions
Use the edge coordinates as a starting guess for:
- Map center
- Initial location suggestions
- Region-specific markers
Then refine with:
- Postcode/ZIP entered by the user
- Address autocomplete (Google / Mapbox)
- Explicit browser geolocation (with consent)
Need More Info About Edge Geolocation?
If you're implementing location-aware features, A/B tests, or edge personalisation and need guidance on best practices, accuracy considerations, or provider-specific implementation, let's discuss how to make the most of edge geolocation in your stack.
Book a Free Strategy Call7. Pros and Cons of Edge Geolocation (Across Providers)
Pros
- No extra API calls – cheaper, simpler, fewer failure points
- Minimal latency – runs before your app logic
- Works with cached pages – perfect for static sites & SSR
- Great for country / region targeting
- Ideal for A/B testing and experimentation
Cons
- City-level is unreliable (varies hugely on mobile)
- No postcode-level precision
- VPNs and corporate networks can distort city/region
- Differences in API surface:
- Fastly: headers
- Vercel: req.geo
- Cloudflare: CF-IPCountry + request.cf
8. Hybrid Strategy: Edge Geo + User Data + APIs
The best real-world pattern is hybrid:
- Edge Geo → instant coarse targeting
- Decide copy, layout, high-level variant
- Set defaults (country, region, language)
- User input → precise location
- Postcode / ZIP fields
- Address autocompletion
- External API → accurate coordinates
- Google Maps Geocoding
- Mapbox / other providers
- Browser geolocation (optional)
- "Use my location" button
- Only triggered when user explicitly requests
This way you get:
- Fast, low-cost personalisation
- Precise distance and maps when needed
- Clear user consent for precise location
9. Pitfalls and How to Avoid Them
Pitfall 1 – Using city for distance-based logic
- Don't calculate "X km from you" from purely city-level IP data.
- Use postcodes/addresses + geocoding instead.
Pitfall 2 – Assuming mobile = desktop accuracy
- Mobile traffic is much less precise.
- Always design experiences so they still make sense when the city is wrong.
Pitfall 3 – Relying on one provider's quirks
- Don't couple all logic to a single header like
Fastly-Client-Country. - Abstract it:
function normaliseGeo(source) {
return {
country: source.country || source.countryCode || "",
region: source.region || source.state || "",
city: source.city || "",
latitude: source.latitude || "",
longitude: source.longitude || ""
};
}
Then map Fastly/Vercel/Cloudflare to this internal structure.
Pitfall 4 – Doing everything client-side
- Use edge runtime/middleware where possible:
- Faster
- Works with cached pages
- Allows routing & experiment selection before HTML
10. Conclusion
Edge-level geolocation is one of the most powerful "free" signals provided by modern CDNs such as Fastly, Vercel, and Cloudflare. Used correctly, it enables instant personalisation, smarter A/B tests, and better user experiences without extra APIs or added latency.
However, it is essential to understand the limitations and risks, especially when dealing with town-level or city-level positioning:
- City accuracy is not guaranteed on any provider.
- Mobile carriers routinely reroute traffic through centralised gateways, making users appear hundreds of kilometres away.
- VPNs, corporate firewalls, and ISP quirks can distort the returned city to a completely different region.
- In some countries, the "city" is simply the location of the ISP's data centre — not the user.
This means that while country and region/state values are generally reliable and safe to use for personalisation, town-level or neighbourhood-level decisions are risky and should never be used for anything sensitive, specific, or accuracy-dependent such as:
- Distance calculations
- "Clinics/installers near you" promises
- City-level pricing or offers
- Hyper-local content targeting
For these use cases, always fall back to a hybrid workflow:
- Use edge geolocation for wide targeting (country/region).
- Use postcode / ZIP input for user-provided precision.
- Use geocoding APIs (Google, Mapbox, etc.) for exact coordinates.
- Use browser geolocation only when explicitly requested by the user.
In summary:
Edge geolocation is fast, scalable, and reliable at a high level — but risky and often wrong at the granular "town" level.
Design your experiments and experiences accordingly, and you'll avoid false assumptions while still gaining all the performance benefits of geo-personalisation at the edge.
Frequently Asked Questions
Related reading
Recently, I worked on a project that required integrating Google Maps to help users find the five closest specific activities near their postcode or address. The goal was to display…
Read next: Understanding Google Maps APIs: A Comprehensive Guide to Uses and Costs →