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

nicolalazzari
Geolocation visualization showing map with location markers and edge network connections

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:

  1. Take the visitor's IP address
  2. Look it up in a GeoIP database (MaxMind-style)
  3. 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-Country
  • Fastly-Client-Region
  • Fastly-Client-City
  • Fastly-Client-Latitude
  • Fastly-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

  • country
  • region
  • city
  • latitude
  • longitude

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 Call

7. 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:

  1. Edge Geo → instant coarse targeting
    • Decide copy, layout, high-level variant
    • Set defaults (country, region, language)
  2. User input → precise location
    • Postcode / ZIP fields
    • Address autocompletion
  3. External API → accurate coordinates
    • Google Maps Geocoding
    • Mapbox / other providers
  4. 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:

  1. Use edge geolocation for wide targeting (country/region).
  2. Use postcode / ZIP input for user-provided precision.
  3. Use geocoding APIs (Google, Mapbox, etc.) for exact coordinates.
  4. 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

Edge geolocation is location data (country, region, city, coordinates) that CDNs and edge platforms attach to each request based on the visitor's IP address. This happens before your app code runs, using GeoIP databases like MaxMind. It's available via HTTP headers, environment variables, or edge runtime APIs depending on your provider.
Accuracy varies by level: country-level is ~99% accurate and safe for pricing, language variants, and legal compliance. Region/state is ~85-95% accurate, good for US states, UK regions, and broad targeting. City-level is only 40-70% accurate, especially on mobile, and should not be used for distance calculations or critical decisions.
Fastly exposes geo data via HTTP headers: Fastly-Client-Country, Fastly-Client-Region, Fastly-Client-City, Fastly-Client-Latitude, and Fastly-Client-Longitude. You can check these with curl or access them client-side via a HEAD request. Fastly also optionally provides a JavaScript object (window.FastlyGeo) if configured.
On Vercel (Next.js Edge Runtime), geolocation is available via request.geo in middleware or edge functions. The geo object contains country, region, city, latitude, and longitude. This works in Next.js middleware.ts files and edge API routes, allowing you to make routing and personalisation decisions before HTML is generated.
Cloudflare provides geo data in two ways: via the CF-IPCountry HTTP header (country only) and via request.cf in Cloudflare Workers (full geo object with country, region, city, latitude, longitude). The header is available on all requests, while request.cf is only available in Worker runtime.
Yes, edge geolocation is ideal for location-aware A/B tests. You can assign variants based on country or region in edge middleware (Vercel) or via headers (Fastly/Cloudflare), set a cookie with the variant ID, and have your client-side experimentation tool read that cookie. This works even with cached pages.
City-level accuracy is poor (40-70%) because mobile carriers route traffic through centralised gateways (making users appear in different cities), VPNs and corporate networks distort location, and in some countries the "city" is just the ISP's data centre location. Mobile connections are the biggest source of error.
Use a hybrid approach: (1) Edge geo for instant coarse targeting (country/region for copy, pricing, language), (2) User input (postcode/ZIP) for precision, (3) Geocoding APIs (Google Maps, Mapbox) for exact coordinates when needed, (4) Browser geolocation only when explicitly requested. This gives fast personalisation with precise data when required.
Yes, that's one of the major advantages. Edge geolocation works with cached pages because the geo data is attached to the request before your app code runs. This makes it perfect for static sites, SSR, and CDN-cached content where you still want location-based personalisation.
Common pitfalls include: (1) Using city data for distance calculations (use postcodes + geocoding instead), (2) Assuming mobile accuracy equals desktop (mobile is much less precise), (3) Coupling logic to one provider's specific headers (abstract with a normaliseGeo function), (4) Doing everything client-side (use edge middleware for better performance).

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

Related Resources