Intermediate
How to configure geo routing with middleware on Vercel
Quick Answer
Configure geo routing on Vercel by creating middleware that reads the country code from request headers and redirects users based on their location. Use Vercel's built-in geo headers to implement country-specific routing rules.
Prerequisites
- Vercel account with active project
- Basic knowledge of Next.js middleware
- Understanding of HTTP requests and geography-based routing
- Node.js development environment
1
Create the middleware file
In your project root, create a
middleware.js or middleware.ts file. This file will intercept all incoming requests before they reach your pages.// middleware.js
import { NextResponse } from 'next/server'
export function middleware(request) {
// Middleware logic will go here
}
export const config = {
matcher: '/((?!api|_next/static|_next/image|favicon.ico).*)'
}Tip
Place the middleware file at the project root level, not inside the pages or app directory
2
Access geo location data
Use Vercel's built-in geo headers to detect user location. The
request.geo object contains country, region, and city information.export function middleware(request) {
const country = request.geo?.country || 'US'
const region = request.geo?.region
const city = request.geo?.city
console.log(`User from: ${city}, ${region}, ${country}`)
}Tip
Vercel automatically populates geo data - no additional setup required for basic location detection
3
Define routing rules
Create routing logic based on country codes. Set up redirects or rewrites for different geographical regions.
export function middleware(request) {
const country = request.geo?.country || 'US'
const { pathname } = request.nextUrl
// Skip if already on a geo-specific path
if (pathname.startsWith('/us') || pathname.startsWith('/eu') || pathname.startsWith('/asia')) {
return NextResponse.next()
}
// Define country-to-region mapping
const euCountries = ['DE', 'FR', 'IT', 'ES', 'NL', 'GB']
const asiaCountries = ['JP', 'CN', 'IN', 'SG', 'KR']
if (euCountries.includes(country)) {
return NextResponse.redirect(new URL(`/eu${pathname}`, request.url))
} else if (asiaCountries.includes(country)) {
return NextResponse.redirect(new URL(`/asia${pathname}`, request.url))
}
// Default to US
return NextResponse.redirect(new URL(`/us${pathname}`, request.url))
}Tip
Use ISO 3166-1 alpha-2 country codes (like 'US', 'GB', 'DE') for consistency
4
Handle language preferences
Combine geo routing with language detection from the
Accept-Language header for more sophisticated routing.export function middleware(request) {
const country = request.geo?.country || 'US'
const acceptLanguage = request.headers.get('accept-language') || ''
const { pathname } = request.nextUrl
// Extract preferred language
const preferredLang = acceptLanguage.split(',')[0]?.split('-')[0] || 'en'
// Route based on country and language
if (country === 'DE') {
const lang = preferredLang === 'de' ? 'de' : 'en'
return NextResponse.redirect(new URL(`/${lang}/de${pathname}`, request.url))
}
// Add similar logic for other countries
}Tip
Always provide fallback languages to ensure users can access your content
5
Create geo-specific pages
Organize your pages directory to match your routing structure. Create folders for each geographical region.
Each regional page can contain location-specific content, pricing, or features.
pages/
├── us/
│ ├── index.js
│ └── about.js
├── eu/
│ ├── index.js
│ └── about.js
├── asia/
│ ├── index.js
│ └── about.js
└── index.js (fallback)Each regional page can contain location-specific content, pricing, or features.
Tip
Consider using dynamic imports to load region-specific components and reduce bundle size
6
Add bypass mechanism
Implement a way for users to override geo routing using URL parameters or cookies for testing and user preference.
export function middleware(request) {
const { searchParams, pathname } = request.nextUrl
const country = request.geo?.country || 'US'
// Check for region override
const regionOverride = searchParams.get('region')
const cookieRegion = request.cookies.get('preferred-region')?.value
if (regionOverride && ['us', 'eu', 'asia'].includes(regionOverride)) {
const response = NextResponse.redirect(new URL(`/${regionOverride}${pathname}`, request.url))
response.cookies.set('preferred-region', regionOverride, { maxAge: 86400 * 30 })
return response
}
if (cookieRegion) {
return NextResponse.redirect(new URL(`/${cookieRegion}${pathname}`, request.url))
}
// Continue with geo-based routing
}Tip
Use query parameters like ?region=eu for easy testing during development
7
Deploy and test
Deploy your changes to Vercel and test geo routing functionality. Use Vercel's Edge Network to verify routing from different locations.
Test using:
Monitor the Functions tab in your Vercel dashboard to see middleware execution logs.
Test using:
- Vercel CLI:
vercel devfor local testing - Browser DevTools: Override headers in Network tab
- VPN services: Test from different geographical locations
- Vercel Edge Functions: Check logs in dashboard
Monitor the Functions tab in your Vercel dashboard to see middleware execution logs.
Tip
Use Vercel Analytics to monitor the effectiveness of your geo routing strategy
Troubleshooting
Middleware not executing or geo data is undefined
Ensure your middleware file is in the project root and check that you're on a Vercel Pro plan or higher. Geo data is only available on Edge Runtime, verify your
config.runtime is not set to Node.js.Infinite redirect loops occurring
Add proper path checks to prevent redirecting already geo-routed URLs. Use
pathname.startsWith('/us') conditions to exit early when users are already on the correct regional path.Geo routing not working in development
Geo headers are only available in production on Vercel. For local testing, mock the geo data by setting default values:
const country = request.geo?.country || 'US' or use the Vercel CLI with --prod flag.SEO issues with geo redirects
Use
NextResponse.rewrite() instead of redirect() for better SEO, or implement proper canonical tags and hreflang attributes. Consider using 302 status codes for temporary geo-based redirects.Ready to get started with Vercel?
Put this tutorial into practice. Visit Vercel and follow the steps above.
Visit Vercel →