Geolocation lets you show or hide content based on the visitor’s country — useful for region-restricted products, localised promotions, or GDPR-specific consent flows. The approach: detect the client IP, query a geolocation API, and act on the result.
Problem: How do you detect a visitor's country or city in WordPress — for example, to show localised content or restrict access by geography — without requiring them to fill in a form?
Solution: Retrieve the visitor's IP address from $_SERVER (checking HTTP_X_FORWARDED_FOR for proxy headers first), then query a free geolocation API such as ip-api.com via wp_remote_get() and cache the result in a transient to avoid hitting the rate limit on every request.
A reliable helper that handles proxy headers and falls back gracefully:
function get_client_ip() {
$headers = [
'HTTP_CF_CONNECTING_IP', // Cloudflare
'HTTP_X_FORWARDED_FOR', // load balancers / proxies
'HTTP_CLIENT_IP',
'REMOTE_ADDR', // direct connection
];
foreach ( $headers as $header ) {
$ip = getenv( $header ) ?: ( $_SERVER[ $header ] ?? '' );
if ( $ip ) {
// X_FORWARDED_FOR may contain a list — take the first one
$ip = trim( explode( ',', $ip )[0] );
if ( filter_var( $ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE ) ) {
return $ip;
}
}
}
return '';
}
function get_client_country() {
$ip = get_client_ip();
$api_key = defined( 'IPGEO_API_KEY' ) ? IPGEO_API_KEY : '';
if ( ! $ip || ! $api_key ) return '';
$transient = 'geo_country_' . md5( $ip );
$cached = get_transient( $transient );
if ( $cached !== false ) return $cached;
$url = "https://api.ipgeolocation.io/ipgeo?apiKey={$api_key}&ip={$ip}&fields=country_name";
$response = wp_remote_get( esc_url_raw( $url ), [ 'timeout' => 3 ] );
if ( is_wp_error( $response ) ) return '';
$data = json_decode( wp_remote_retrieve_body( $response ), true );
$country = $data['country_name'] ?? '';
set_transient( $transient, $country, HOUR_IN_SECONDS );
return $country;
}
// Redirect non-US visitors away from US-only product pages
add_action( 'template_redirect', function() {
if ( is_singular( 'product' ) && get_field( 'show_for_usa' ) ) {
if ( get_client_country() !== 'United States' ) {
wp_redirect( home_url() );
exit;
}
}
} );
Add your API key to wp-config.php (register for free at ipgeolocation.io):
define( 'IPGEO_API_KEY', 'your_api_key_here' );
NOTE: Cache the geolocation result per IP with a transient (as shown above) to avoid hitting the API on every page load. Free-tier plans typically allow 1,000 requests per day — without caching, a single user browsing multiple pages would exhaust that quota in minutes. Also note that IP-based geolocation is not 100% accurate and should not be used as the sole mechanism for legally required access control.