Search code examples
phpgeo

PHP GEO location redirect - Are there any better solutions?


EDIT: Wasn't a duplicate to began with. Originally was how to improve or use different code to redirect based on the visitor's COUNTRY.

Here is the code I'm currently using:

require_once('geo/geoip.inc');
$gi = geoip_open('geo/GeoIP.dat', GEOIP_MEMORY_CACHE);
$country = geoip_country_code_by_addr($gi, $_SERVER['REMOTE_ADDR']);
geoip_close($gi);

if ($country == 'FR') { 
header('Location: http://fr.mysite.com');
}

if ($country == 'US') { 
header('Location: http://us.mysite.com');
}

on a couple of static (html + javascript) viral sites that bring in around 100,000 visitors a day, sometimes more and sometimes less.

Are there any better (and free) solutions to redirect based on country? I recently switched from a dedicated server to a VPS and the current code seems to use a lot of CPU usage (or so I'm told by my host). I'll probably just go back to the dedicated server but I would still like to know if there is a better way, one that doesn't stress the server as much.

Also, since I'm redirecting based on language:

// french
if ($country == 'FR') { 
header('Location: http://fr.mysite.com');
}

//french
if ($country == 'BE') { 
header('Location: http://fr.mysite.com');
}

//french
if ($country == 'CA') { 
header('Location: http://fr.mysite.com');
}

//english
if ($country == 'US') { 
header('Location: http://us.mysite.com');
}

//english
if ($country == 'UK') { 
header('Location: http://us.mysite.com');
}

and extremely tired right now, what's the better way? this or no:

    //english
    if ($country == 'US') || ($country == 'CA') { 
    header('Location: http://us.mysite.com');
    }

So anyone visiting from US or Canada would be redirected to google.com

Thanks in advance


Solution

  • EDIT: Source ended up being an answer to the duplicate question.

    If the only differences between the sites are languages and nothing to do with their actual country, you should be redirecting based on preferred language instead.

    However, this gets really complex, as HTML headers can contain multiple languages, with certain languages preferred over others. A solution I found a while back, and unfortunately cannot find the original source to is to make a list of available languages, parse the languages out of the HTML Header with their order of preference, and determine based on that which redirect to follow:

    I DO NOT OWN THE prefered_language() FUNCTION AND DID NOT TAKE ANY PART IN ITS CREATION! But I can't find the original anywhere.. If someone else is able to, please, link it...

    $available_languages = array("en", "fr");
    
    $default_language = "en";
    
    function prefered_language($available_languages, $http_accept_language) {
        global $default_language;
        $available_languages = array_flip($available_languages);
        $langs = array();
        preg_match_all('~([\w-]+)(?:[^,\d]+([\d.]+))?~', strtolower($http_accept_language), $matches, PREG_SET_ORDER);
        foreach($matches as $match) {
            list($a, $b) = explode('-', $match[1]) + array('', '');
            $value = isset($match[2]) ? (float) $match[2] : 1.0;
            if(isset($available_languages[$match[1]])) {
                $langs[$match[1]] = $value;
                continue;
            }
            if(isset($available_languages[$a])) {
                $langs[$a] = $value - 0.1;
            }
        }
        if($langs) {
            arsort($langs);
            return key($langs);
        } else {
            return $default_language;
        }
    }
    
    if(isset($_COOKIE["client_lang"])){
      $lang = $_COOKIE["client_lang"];
    }else{
      $lang = prefered_language($available_languages, strtolower($_SERVER["HTTP_ACCEPT_LANGUAGE"]));
      setcookie("client_lang", $lang, time() + (86400 * 30 * ), "/");
    }
    
    header('Location: http://' . $lang . '.mysite.com');
    

    I'd also suggest creating a cookie for the client's preferred language as I have done above, since this function will still require some CPU usage.