How to Redirect a Website Based on Location (Step-by-Step)
A hands-on, step-by-step guide to setting up location-based website redirects. Covers URL structure decisions, edge vs server vs client detection, bot handling, hreflang tags, and a no-code path with GeoSwap.

Your website gets traffic from 30 countries, but every visitor sees the same page. The French visitor lands on your English homepage. The Brazilian visitor sees USD pricing. The Australian visitor gets shipping estimates for North America. Each of these is a missed conversion — and the fix is location-based redirects.
This guide is a hands-on, step-by-step walkthrough of how to set up website redirects based on visitor location. We cover the technical architecture, code examples for every major approach, the SEO rules you cannot afford to ignore, and a no-code path for teams that want results without infrastructure work.
How location-based redirects work (the 30-second version)
Every visitor to your website has an IP address. That IP maps to a geographic location with high accuracy — 99.5% at the country level, according to MaxMind. When a request hits your site, the system looks up the IP, resolves it to a country (and optionally a state or city), and either serves the default page or redirects to a localized version.
The redirect should always be a 302 (temporary), not a 301 (permanent), because the same URL should serve different destinations depending on who is visiting. A 301 tells search engines to permanently replace the URL in their index, which is the wrong signal for conditional routing.
Step 1: Decide your URL structure
Before writing any code, you need a plan for where each country's visitors will land. There are three common structures:
Subfolders (recommended for most sites)
yoursite.com/ → Default (usually English/US)
yoursite.com/de/ → Germany
yoursite.com/fr/ → France
yoursite.com/ja/ → Japan
yoursite.com/pt-br/ → BrazilSubfolders keep all your content under one domain, which consolidates domain authority for SEO. This is what Google recommends for most sites. According to a 2024 study by Ahrefs analyzing 10,000+ international sites, subfolder structures averaged 31% more organic traffic than subdomain equivalents.
Subdomains
yoursite.com → Default
de.yoursite.com → Germany
fr.yoursite.com → France
jp.yoursite.com → JapanSubdomains make sense when each region runs on separate infrastructure (different CMS, different hosting). The downside: Google treats each subdomain as a somewhat separate entity, which can dilute your domain authority. Read our multi-regional SEO strategy guide for a deeper comparison.
Separate domains (ccTLDs)
yoursite.com → Default
yoursite.de → Germany
yoursite.fr → France
yoursite.co.jp → JapanCountry-code top-level domains send the strongest geo signal to search engines, but they are the most expensive and complex to manage. Each domain needs its own SEO strategy, link building, and SSL certificates.
Step 2: Choose your detection method
Location detection happens at one of three layers. The layer you choose determines your performance, reliability, and platform compatibility.
Edge layer (fastest, recommended)
CDN providers attach geolocation data to every request as a free header. Cloudflare adds CF-IPCountry, Vercel adds X-Vercel-IP-Country, and AWS CloudFront adds CloudFront-Viewer-Country. The redirect happens in the edge node closest to the visitor, typically within 10 milliseconds.
Here is a complete Cloudflare Worker for location-based redirects with multiple countries:
// Cloudflare Worker — location-based redirects
const COUNTRY_ROUTES = {
DE: '/de/',
FR: '/fr/',
JP: '/ja/',
BR: '/pt-br/',
ES: '/es/',
IT: '/it/',
KR: '/ko/',
NL: '/nl/',
};
// Known search engine and AI bot user agents
const BOT_PATTERNS = [
'googlebot', 'bingbot', 'yandexbot', 'baiduspider',
'gptbot', 'claudebot', 'perplexitybot',
];
function isBot(userAgent) {
const ua = (userAgent || '').toLowerCase();
return BOT_PATTERNS.some(bot => ua.includes(bot));
}
export default {
async fetch(request) {
const url = new URL(request.url);
// Only redirect on the homepage
if (url.pathname !== '/') {
return fetch(request);
}
// Never redirect bots — let them see default content
const ua = request.headers.get('user-agent');
if (isBot(ua)) {
return fetch(request);
}
// Check for a region override cookie
const cookies = request.headers.get('cookie') || '';
if (cookies.includes('geo_override=')) {
return fetch(request);
}
const country = request.cf?.country;
const destination = COUNTRY_ROUTES[country];
if (destination) {
const redirectUrl = url.origin + destination;
return Response.redirect(redirectUrl, 302);
}
return fetch(request);
}
};Server layer
If you run your own backend, you can look up the visitor's IP against a geolocation database. Here is a complete Express.js middleware example:
// Express.js — location-based redirect middleware
const maxmind = require('maxmind');
let lookup;
(async () => {
lookup = await maxmind.open('./GeoLite2-Country.mmdb');
})();
const COUNTRY_ROUTES = {
DE: '/de/',
FR: '/fr/',
JP: '/ja/',
BR: '/pt-br/',
};
// Bot detection by user agent
const BOT_REGEX = /googlebot|bingbot|yandexbot|gptbot|claudebot/i;
app.use((req, res, next) => {
// Skip if not the homepage
if (req.path !== '/') return next();
// Skip bots
if (BOT_REGEX.test(req.headers['user-agent'])) return next();
// Skip if user has a region override cookie
if (req.cookies?.geo_override) return next();
// Look up the visitor's country
const ip = req.headers['x-forwarded-for']?.split(',')[0] || req.ip;
const result = lookup?.get(ip);
const country = result?.country?.iso_code;
const destination = COUNTRY_ROUTES[country];
if (destination) {
return res.redirect(302, destination);
}
next();
});Key trade-off: Server-side redirects require every request to reach your origin, adding latency for distant visitors. A user in Tokyo hitting a server in Virginia adds 150-200ms round-trip before the redirect even fires.
Client layer (avoid if possible)
JavaScript-based redirects call a third-party geolocation API after the page has loaded. We do not recommend this approach for several reasons covered in detail in our article on content flash (FOUC). In short: the page loads visibly before the redirect fires, ad blockers interfere with the API call, and search engines do not reliably execute JavaScript redirects.
Step 3: Implement bot detection
This step is non-negotiable for SEO safety. Search engine crawlers must bypass your location-based redirects and see your default content. If Googlebot gets redirected to your German page, Google may index the German version as your primary content and serve it to English-speaking searchers.
Bot detection works at two levels:
- User-agent matching: Check the request's User-Agent header against known bot signatures. This catches Googlebot, Bingbot, and most AI crawlers. The code examples above include this check.
- IP verification: For critical sites, verify that the IP address actually belongs to the claimed bot. Googlebot publishes its IP ranges, and a reverse DNS lookup on the IP should resolve to
*.googlebot.com. This prevents malicious actors from spoofing the Googlebot user agent.
“If you want to target users in different countries, use hreflang to swap the right page in search results rather than geo-redirecting — that way, Google can still crawl and index all versions.”
Mueller's advice is sound: hreflang tags and geo redirects serve complementary purposes. Hreflang tells search engines which version to show in results; geo redirects handle visitors who land on the wrong version directly. You need both.
Step 4: Add hreflang tags
Hreflang tags tell search engines the relationship between your localized pages. Without them, Google may treat your French and English pages as duplicate content. Add them to the <head> of every localized page:
<!-- On yoursite.com/ (default English) -->
<link rel="alternate" hreflang="en" href="https://yoursite.com/" />
<link rel="alternate" hreflang="de" href="https://yoursite.com/de/" />
<link rel="alternate" hreflang="fr" href="https://yoursite.com/fr/" />
<link rel="alternate" hreflang="ja" href="https://yoursite.com/ja/" />
<link rel="alternate" hreflang="x-default" href="https://yoursite.com/" />
<!-- On yoursite.com/de/ (German) -->
<link rel="alternate" hreflang="en" href="https://yoursite.com/" />
<link rel="alternate" hreflang="de" href="https://yoursite.com/de/" />
<link rel="alternate" hreflang="fr" href="https://yoursite.com/fr/" />
<link rel="alternate" hreflang="ja" href="https://yoursite.com/ja/" />
<link rel="alternate" hreflang="x-default" href="https://yoursite.com/" />Every localized page must include the full set of hreflang tags, and the tags must be reciprocal (each page points to all others). Our free hreflang tag generator creates the correct markup for any number of pages and languages. Run your existing tags through our hreflang checker to catch common implementation errors.
Step 5: Build a region override mechanism
Not every visitor wants to be automatically redirected. A German citizen living in Tokyo should be able to switch to the German version of your site. Implement this with a cookie:
// When the user clicks a region selector
function setRegionOverride(region) {
document.cookie = `geo_override=${region}; path=/; max-age=${30 * 24 * 60 * 60}`;
window.location.href = `/${region}/`;
}
// Your redirect logic should check for this cookie
// and skip the automatic redirect if it existsThe cookie should persist for at least 30 days. Place a visible language or region selector in your site's header or footer. According to a Baymard Institute study, 68% of users expect to find a language selector in the site header or footer.
Step 6: Test from every target country
You cannot trust location-based redirects without testing them from the actual target countries. Read our complete guide to testing your website from another country for the full methodology. The short version:
- Use a VPN to connect from each target country and verify the redirect.
- Check that the HTTP status code is 302, not 301.
- Verify that visiting from an unconfigured country shows your default content.
- Confirm that the region override cookie prevents re-redirect.
- Use Google Search Console's URL Inspection to verify Googlebot is not being redirected.
The no-code approach: GeoSwap
If the code above looks like more infrastructure than you want to manage, GeoSwap's GeoRedirect gives you the same result without writing code. The setup takes about five minutes:
- Sign up for GeoSwap (free, no credit card).
- Add your domain and install the script tag.
- Create redirect rules: specify the source country and the destination URL.
- Publish. Redirects are live immediately.
GeoSwap uses Cloudflare Workers under the hood, so you get the same edge-side performance as the custom implementation above. It also handles the details that are easy to get wrong in a custom build:
- Automatic bot detection: Search engine and AI crawlers bypass all redirect rules by default.
- 302 by default: You cannot accidentally use 301s.
- Exclusion rule warnings: If you create a rule like “redirect everyone NOT in the US,” the dashboard flags the SEO risk before you publish.
- Chain detection: Alerts you when redirect rules could create loops.
- Analytics: See which countries are generating traffic and how many visitors are being redirected.
GeoSwap works on any platform — Shopify, WordPress, Webflow, custom-built sites — anywhere you can add a script tag. And it's completely free, with no pageview limits or premium tiers.
Advanced: PHP location-based redirect
PHP remains one of the most common server-side languages, powering WordPress and many custom sites. Here is a PHP implementation using MaxMind's GeoIP2 library:
<?php
// composer require geoip2/geoip2
require 'vendor/autoload.php';
use GeoIp2\Database\Reader;
$reader = new Reader('/usr/share/GeoIP/GeoLite2-Country.mmdb');
// Skip bots
$userAgent = $_SERVER['HTTP_USER_AGENT'] ?? '';
$botPatterns = ['googlebot', 'bingbot', 'yandexbot', 'gptbot', 'claudebot'];
$isBot = false;
foreach ($botPatterns as $bot) {
if (stripos($userAgent, $bot) !== false) {
$isBot = true;
break;
}
}
if (!$isBot && $_SERVER['REQUEST_URI'] === '/') {
// Check for region override cookie
if (!isset($_COOKIE['geo_override'])) {
$ip = $_SERVER['HTTP_X_FORWARDED_FOR']
?? $_SERVER['REMOTE_ADDR'];
$ip = explode(',', $ip)[0]; // Handle multiple IPs
try {
$record = $reader->country($ip);
$country = $record->country->isoCode;
$routes = [
'DE' => '/de/',
'FR' => '/fr/',
'JP' => '/ja/',
'BR' => '/pt-br/',
];
if (isset($routes[$country])) {
header('Location: ' . $routes[$country], true, 302);
exit;
}
} catch (Exception $e) {
// IP not found in database — serve default content
}
}
}For WordPress sites, this logic can be added to your theme's functions.php or wrapped in a plugin. However, we recommend reading our WordPress geo-targeting guide for the full picture, including caching compatibility and plugin alternatives.
Advanced: Python (Django/Flask) location-based redirect
For Python web applications, the geoip2 library provides the same MaxMind database access:
# Django middleware — geo_middleware.py
import geoip2.database
import re
reader = geoip2.database.Reader('/usr/share/GeoIP/GeoLite2-Country.mmdb')
BOT_REGEX = re.compile(
r'googlebot|bingbot|yandexbot|gptbot|claudebot',
re.IGNORECASE
)
COUNTRY_ROUTES = {
'DE': '/de/',
'FR': '/fr/',
'JP': '/ja/',
'BR': '/pt-br/',
}
class GeoRedirectMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
# Only redirect on homepage
if request.path != '/':
return self.get_response(request)
# Skip bots
user_agent = request.META.get('HTTP_USER_AGENT', '')
if BOT_REGEX.search(user_agent):
return self.get_response(request)
# Skip if override cookie set
if request.COOKIES.get('geo_override'):
return self.get_response(request)
# Get visitor IP
ip = request.META.get(
'HTTP_X_FORWARDED_FOR', request.META['REMOTE_ADDR']
).split(',')[0].strip()
try:
response = reader.country(ip)
country = response.country.iso_code
destination = COUNTRY_ROUTES.get(country)
if destination:
from django.http import HttpResponseRedirect
return HttpResponseRedirect(destination)
except Exception:
pass
return self.get_response(request)Monitoring your redirects in production
Setting up redirects is step one. Monitoring them is step two. Without monitoring, you will not know if a rule breaks, a new country starts sending significant traffic, or a redirect chain forms after a site update.
- Analytics segmentation: In Google Analytics, segment your traffic by country and landing page. If French visitors are landing on the English homepage instead of /fr/, your redirect is not working for some visitors.
- Server log analysis: Look for 302 responses in your server logs to verify redirects are firing. If you see 301s where you expect 302s, you have a configuration problem.
- Uptime monitoring: Configure uptime checks from multiple global locations. Services like UptimeRobot and Pingdom can alert you if a redirect returns an error instead of a 302.
- GeoSwap analytics: If you use GeoSwap, the dashboard shows redirect analytics per country — how many visitors matched each rule, where they were redirected, and any errors.
Location-based redirects vs content personalization
Redirects are not the only way to customize the experience by location. Content personalization ( GeoContent) lets you swap specific elements on a page — pricing, banners, phone numbers, CTAs — without redirecting to a different URL. The comparison:
- Use redirects when: You have fully separate localized pages (different language, different product catalog, different legal requirements).
- Use content personalization when: The page structure is the same, but specific elements need to change (currency, promo banner, phone number, shipping info).
- Use both when: You redirect to localized pages AND personalize content within those pages. For example, redirect UK visitors to
/uk/and then show a region-specific promotion banner on that page.
Read our guide to showing different content by country for a deep dive on the content personalization side.
Comparing approaches at a glance
| Approach | Speed | SEO Safety | Platform Support | Cost |
|---|---|---|---|---|
| Edge (Cloudflare Workers) | Under 10ms | High (with bot detection) | Any | Free tier available |
| Server-side (Node/PHP) | 50-200ms | High (with bot detection) | Requires own server | Free (MaxMind GeoLite2) |
| Client-side (JavaScript) | 500ms+ | Low (cloaking risk) | Any | API costs at scale |
| GeoSwap (no-code) | Under 10ms | High (automatic) | Any | Free |
Frequently asked questions
How do I redirect a website based on location without coding?
Use a geo-targeting tool like GeoSwap's GeoRedirect. Add a script tag to your site, create redirect rules in the visual dashboard, and publish. Redirects execute at the edge with no code required. It works on Shopify, WordPress, Webflow, and any custom site.
What is the difference between a geo redirect and a geo block?
A geo redirect sends visitors from a specific country to a different page (usually a localized version of the same content). A geo block prevents visitors from a specific country from accessing the site entirely, usually showing an “unavailable in your region” message. Redirects are for localization; blocks are for compliance (sanctions, licensing restrictions).
Do location-based redirects affect page speed?
Edge-side redirects (Cloudflare Workers, Vercel Edge Middleware) add less than 10 milliseconds and happen before the page loads, so there is no perceptible impact. Server-side redirects add the round-trip time to your origin server. Client-side JavaScript redirects are the worst for performance — the original page loads completely before the redirect fires.
Can I redirect based on city or state, not just country?
Yes. IP geolocation supports country, state/region, and city-level detection. Country-level accuracy is 99.5%, state-level is 80-90%, and city-level is 70-80%. GeoSwap supports all three levels. For most use cases, country-level redirects are sufficient — use state or city only when you have a specific need (like showing CCPA notices only in California).
Should I redirect based on browser language or IP location?
IP location is more reliable. Browser language settings reflect the user's software configuration, not their physical location. A French expatriate in the US will have their browser set to French, but should probably see US pricing and shipping information. IP-based detection correctly identifies them as being in the US, while browser language would incorrectly redirect them to the French site.
How do I handle visitors using VPNs?
VPN users are redirected based on the VPN server's location, not their real location. This is generally acceptable behavior — if someone is routing their traffic through a German server, serving them the German experience is reasonable. The key is to always provide a manual region selector so any visitor can override the automatic redirect.
How do I test location-based redirects before going live?
Use a VPN to connect from each target country and visit your site. Verify the redirect fires, check that the HTTP status code is 302, and confirm the destination URL is correct. Our complete testing guide covers six different methods for testing from other countries, including automated approaches with Playwright.
What happens if the geolocation database is wrong?
No geolocation database is 100% accurate. At the country level, accuracy is 99.5%, which means roughly 1 in 200 visitors may be detected as the wrong country. The region override mechanism (cookie-based region selector) handles this gracefully — affected visitors can manually select their correct region. Geolocation databases update frequently (MaxMind updates weekly) to improve accuracy.
Can I redirect visitors from specific regions within a country?
Yes. IP geolocation provides state/region-level data (80-90% accuracy) and city-level data (70-80% accuracy). Common use cases include showing CCPA compliance notices only to California visitors, or redirecting visitors from Quebec to a French-language page. Both custom implementations and GeoSwap support sub-country targeting.
Location-based redirects are one of the highest-impact improvements you can make for an international website. The technical implementation is straightforward — edge-side detection with 302 redirects, bot-transparent architecture, and hreflang tags. The hard part is getting the details right: no 301s, no exclusion rules, always a fallback, always an override. Whether you build it yourself or use GeoSwap to handle the infrastructure, start with our geo redirect documentation and test thoroughly from every target country with our redirect checker and IP lookup tool.
