Country Redirect

Easily redirect visitors to a locale based on their country of origin

Installation #

To install Country Redirect, follow these steps:

  1. Download & unzip the file and place the countryredirect directory into your craft/plugins directory
  2. Install plugin in the Craft Control Panel under Settings > Plugins
  3. The plugin folder should be named countryredirect for Craft to see it.

Country Redirect works on Craft 2.4.x and higher, and requires PHP 7 or higher

Using the plugin #

Before you start using the plugin, you have to do 3 things:

  1. Download a updated country database database from MaxMind through the plugin settings
  2. Copy the configuration file countryredirect.php into the Craft config directory, usually craft/config
  3. Modify the configuration file to match preferences, and make sure you setup the countryMap setting to match your locales.

Configuration #

return [
    '*' => [
         * Enable for all users
        //'enabled'             => true,
         * Or specifically logged in/anon users
        'enabled'             => [
            'loggedIn'  => true,
            'anonymous' => true,

         * Don't redirect bots/crawlers like GoogleBot, Bing etc.
        'ignoreBots'          => true,

         * Add any special URL segments you want to ignore
         * Eg. 'ignoreSegments' => [
         *     'this/page/only/exists/in/one/locale',
         *     'global-page'
         * ],
        'ignoreSegments'      => [ ],

         * Cookie name
        'cookieName'          => 'countryRedirect',

         * The URL parameter that let a user manually select which locale they want to see
        'overrideLocaleParam' => 'selected-locale',

         * The URL parameter that indicates that a user was redirect
        'redirectedParam' => 'redirected',

         * Map a countrys two-letter ISO code to a Craft locale, and/or define a catch-all with a * asterix
         * Here is a list of ISO country codes:
         * Example:
         * 'countryMap'       => [
         *   'FR' => 'fr',
         *   'DK' => 'da',
         *   // You can also send visitors to an arbitrary URL
         *   'DE' => '',
         *   '*' => 'en_us',
         * ]
         * If you within a country have different regional languages, you can map the different languages to locales.
         * Take Switzerland, with German, French, Italian and Romansh, as an example:
         * 'countryMap'       => [
         *   'CH' => [
         *     'fr' => 'fr',
         *     'de' => 'de',
         *   ],
         *   '*' => 'en_us',
         * ]
         * This works by checking the Accept-Language header of the browser.
        'countryMap'          => [ ],

         * If you want to show a banner that prompts visitors to their matching locale instead of redirecting them,
         * you can define these here.
         * The key here is the Craft locale id, not the country code. The variables {countryName} and {url} will
         * be replaced.
         * 'banners' => [
         *   'en_us' => 'It looks like your visiting from {countryName}. Do you <a href="{url}">want to visited the international site?</a>'
         * ],
        'banners'             => [ ],

For a list of the ISO country codes, check out this overview

<h1>Select country</h1>

{% set titles = {
    'en_us': 'Go to our US site',
    'fr': 'Go to our French site',
    'da': 'Go to our Danish site',
} %}
<nav class="nav">
    {% for locale in craft.countryRedirect.getLinks() %}
        {{locale.getLink({ title: titles[locale.getId()] })}}
    {% endfor %}

Visitor information #

Country Redirect has a few helper methods to access visitor information.

To access information:

{% set info = %}
{% if info %}
    <p>Your located in {{ }} ( {{ info.isoCode }})</p>
{% endif %}

To check if a user was redirected:

{% if craft.countryRedirect.redirected() %}
    <p>You were redirected because of your location, which is {{ info ? info.isoCode }} ({{ info ? }})</p>
{% endif %}

To display a message when a visitor overrides their locale:

{% if craft.countryRedirect.overridden() %}
    <p>You have overridden your locale, which is now {{ craft.locale }}</p>
{% endif %}

If you want to show a banner that prompts visitors to their matching locale instead of redirecting them, you can define the text for each locale with the banners setting.

You can then access the text like this:

{% set banner = craft.countryRedirect.getBanner() %}
{% if banner %}
    <div class="banner">
        <p>{{ banner.getText() }}</p>
{% endif %}

Testing #

You can test it by using a free VPN account from TunnelBear

Database #

Geolocation data is provided by MaxMind. According to them, their databases is 99.8% accurate on a country level.

Accuracy #

Roadmap #

  • Make it easier to map locales with a larger amount of country codes
  • Port to Craft 3
  • Make it possible to test locally
  • Add environment checks


The Country Redirect plugin has been great. It works exactly as described, was a snap to setup, and I love that you can update the geolocation database via a cron job. Fred’s support has been top notch too. If you’re looking to implement similar functionality I’d highly recommend checking this plugin out.

Brett Burwell Brett Burwell

Frequently asked questions

How many sites does 1 license cover?

It's pretty simple: 1 license covers 1 site / Craft installation.

Does Google condone location based redirects?

After doing quite a bit of research including reading Google's own documentation on this, I've come to the following conclusions

Can I get country information without redirecting visitors?

Yep. Just set enabled to false.

Can I test the plugin locally?

Since you won't have a valid IP address when accessing the site from localhost, the plugin won't be able to detect the country.

I'm having problems downloading the database

As a first step, check the logs (craft.log, phperrors.log and countryredirect.log) to see if it gives you any error messages.

Do I have to update the database regularly?

Even if you don't do it regularly, the coverage will still be pretty good. If there is no good reason not to, I’d recommend that you do it once a month.

There is a special url you can call to update it automatically.


1.1.6 — 2018-02-02
  • Fixed: Make updateDatabase available by anonymous access
1.1.5 — 2017-11-03
  • Fixed: Fixed error when getCountryLocale would sometimes return array
1.1.4 — 2017-10-31
  • Fixed: Fixed bug that caused redirect to break in previous version
  • Fixed: Fixed `enabled->loggedIn setting`. The setting will now be honored, and all users (anon and logged in) will be redirected by default.
1.1.3 — 2017-10-25
  • Fixed: Fixed check that skips redirect if in Live Preview mode
1.1.2 — 2017-10-25
  • Added: Added check to disable `redirected` url param if disabled
  • Fixed: Fixed a bug where default config values was overwritten even if the config key wasn't in the config.php file
1.1.1 — 2017-10-25
  • Added: Added support for mapping regional languages of a country to locales
  • Improved: Skip redirect check if in live preview mode
  • Improved: Made banner check cookie name configurable
1.1.0 — 2017-06-22
  • Improved: Option to map countries to arbitrary URLs
1.0.9 — 2017-06-20
  • Added: Added support for banner prompts, so that you can display a banner instead of redirecting visitors automatically.
1.0.8 — 2017-05-20
  • Improved: Made resolving of database path more robust
  • Added: Added check to make sure database path exists.
1.0.7 — 2017-05-10
  • Improved: Updated CrawlerDetect
  • Improved: Simplified IP detection
  • Added: Added ignoreSegments config setting, for ignoring certain URL global segments that only exists in one/all locales
1.0.6 — 2017-04-25
  • Added: Added template methods overridden(), redirected() and info()
  • Improved: Improved the IP detection method accuracy, with specific detection for Ezoic, Sucuri, CloudFlare, Akamai, Fastly and standard proxies (HTTP_X_FORWARDED_FOR)
1.0.5 — 2017-04-24
  • Improved: Added ignoreBots setting, so Googlebot etc. won't be redirected.
1.0.4 — 2017-04-21
  • Fixed: The checksum routine now uses Guzzle instead of fopen
1.0.3 — 2017-04-20
  • Fixed: Now uses Guzzle/cURL to download the database, so servers with allow_url_open disabled won't throw up
1.0.2 — 2017-04-20
  • Improved: Removed PHP7-only features to make it compatible with PHP 5.4 and above.
1.0.1 — 2017-04-20
  • Improved: Added checks for console and action requests
1.0.0 — 2017-04-17
  • Added: Initial release

Currently available for Craft consulting and custom plugin development

Contact me