Skip to content

Latest commit

 

History

History
485 lines (371 loc) · 18.2 KB

README.md

File metadata and controls

485 lines (371 loc) · 18.2 KB

GeoMate plugin for Craft CMS 5.x

GeoMate is a friend in need for all things geolocation. IP to geo lookup, automatic redirects (based on country, continent, language, etc), site switcher... You name it.

Screenshot

Requirements

This plugin requires Craft CMS 5.0.0-beta.2 or later. The plugin also requires the zlib PHP extension.

IMPORTANT UPDATE

As of December 30th 2019, the GeoLite2 databases are no longer publicly available due to compliance with GDPR and CCPA. Previously, the public URLs for these databases were set as defaults in the GeoMate configuration. As of GeoMate 1.1.0, these have been removed, and you now need to register a maxmind account, get a license key, and configure the download URLs yourself. See the "Downloading the geolocation database" below for more info on how to do this.

As before, you can also download the database manually and put it in your dbPath yourself.

Installation

To install the plugin, either install it from the plugin store, or follow these instructions:

  1. Install with composer via composer require vaersaagod/geomate from your project directory.
  2. Install the plugin in the Craft Control Panel under Settings → Plugins, or from the command line via ./craft install/plugin geomate.
  3. For GeoMate to do anything, you need to configure it, and download the geolocation database.

GeoMate Overview

GeoMate helps you detect the location and language preferences of you visitors, and lets you set up fine-grained rules to help you redirect users to the correct site, or show location/language specific information in your templates.

GeoMate relies on self-hosted Maxmind GeoIP2 databases for geolocation, and no external services are needed to look up IP information. By default GeoMate use the free Maxmind GeoLite2 database, but can easily be configured to use commercial versions of the database as long as it's in the MaxMind DB file format.


Downloading the geolocation database

For GeoMate to be able to get information about an IP address, you need to download a GeoIP2 database. The easiest way to get one, is to use Maxmind's free GeoLite2 database. For better results and more frequent updates, you should consider their commercial alternatives.

To get the GeoLite2 database, you first need to sign up for an account at Maxmind. Once you have access to your users control panel, you need to create a license key. Finally, you can get the download URL by going to the direct download page, and let GeoMate know about them by setting the countryDbDownloadUrl and cityDbDownloadUrl config settings accordingly. At the time of writing, the URLs should be (replace YOUR_LICENSE_KEY with your license key):

'countryDbDownloadUrl' => 'https://download.maxmind.com/app/geoip_download?edition_id=GeoLite2-Country&license_key=YOUR_LICENSE_KEY&suffix=tar.gz',
'cityDbDownloadUrl' => 'https://download.maxmind.com/app/geoip_download?edition_id=GeoLite2-City&license_key=YOUR_LICENSE_KEY&suffix=tar.gz',

Please note, although this is the recommended approach, you can also just download the files manually, or through some other mechanism, and put them in the dbPath yourself.

GeoMate comes with a handy utility that helps you download the database. You can access it by going to Utilities > GeoMate from the control panel main menu. Please check that the settings is as desired, and download the databases by clicking the "Update now" button.

You can also download the database by accessing the geomate/database/update-database controller action directly, or set up a cron job that hits it at regular intervals. The action URL for your installation is shown in the utility.


Using GeoMate

You can get information about the user's location through the craft.geomate.country, craft.geomate.countryCode and craft.geomate.city template variables.

By configuring the redirectMap config setting, you can define the rules for what location or language information is required for each of your sites. If you want to automatically redirect your users to the appropriate site, you can enable the autoRedirectEnabled config setting, or you can use the craft.geomate.redirectInformation template variable to get the information inside your templates, and display a banner or popup to trigger the user to switch site.

GeoMate also provides a helper to build a site switcher, the craft.geomate.getSiteLinks template variable, and some twig functions, addOverrideParam and addRedirectParam, to add the necessary parameters to ensure that GeoMate picks up that the user has selected a specific site.

There's quite a few config settings that can be used to tweak stuff, so make sure you read through it to get an idea of what the defaults are, and how you can use them to your needs.

When working locally, you need to override the IP by using the forceIp config setting for GeoMate to do anything useful (since it would try to look up 127.0.0.1 if you didn't, and that won't return any results).


Configuring

GeoMate can be configured by creating a file named geomate.php in your Craft config folder, and overriding settings as needed.

cacheEnabled [bool]

Default: true
Enables or disables caching of IP data.

cacheDuration [string|int]

Default: 'P7D'
Duration that looked up IP data should be cached, set as a date interval string or an int indicating the number of seconds.

useSeparateLogfile [bool]

Default: true
When enabled, GeoMate will create and use its own log file named geomate.log in Craft's log path.

logLevel [int]

Default: \yii\log\Logger::LEVEL_ERROR
When using GeoMate's log file (ie useSeparateLogfile being set to true), you can specify what log levels should be logged. By default, only errors will be logged, but if you set it to \yii\log\Logger::LEVEL_WARNING or \yii\log\Logger::LEVEL_INFO you'll get more information.

dbPath [string]

Default: ''
Path to GeoIP databases. If none is given (default), the database will be stored in /storage/geomate or whichever path is defined as Craft's storage path.

countryDbFilename [string]

Default: 'GeoLite2-Country.mmdb'
File name of the GeoIP country database.

cityDbFilename [string]

Default: 'GeoLite2-City.mmdb'
File name of the GeoIP city database.

countryDbDownloadUrl [string|null]

Default: null
Download URL for the GeoIP country database.

cityDbDownloadUrl [string|null]

Default: null
Download URL for the GeoIP city database.

downloadDbIfMissing [bool]

Default: false
If a given database is missing when GeoMate tries to do an IP lookup, it'll fail silently, log the error, and not do a redirect or return any redirect information. If you enable this setting, GeoMate will try to download and unpack the database if it is missing.

Make sure you're certain that download works before enabling this. If something goes wrong during the download, GeoMate will continue to try on every request, which could take up alot of resources depending on what fails.

autoRedirectEnabled [bool]

Default: false
Set this to true to enable automatic redirects of users to sites based on the redirectMap config setting.

autoRedirectExclude [array]

Default: []
A list of site handles that should be excluded from automatic redirects.

redirectMap [array]

Default: []
This powerful config setting enables you to create detailed rules for redirecting users to your different sites, based on detected information about location or language.

The easiest way to use this setting is to map site handles to country codes:

'redirectMap' => [
    'norwegian' => 'no',
    'swedish' => 'se',
    'global' => '*' 
]

In this example, there are three sites with handles norwegian, swedish and global. Visitors from Norway is redirected to the norwegian site, visitors from Sweden are redirected to the swedish site, and the rest is sent to the global site.

By default, it's assumed that the value is the detected country code. If redirectMapSimpleModeKey is set to language though, the users browser language is used.

But, you can also use more advanced rules:

'redirectMap' => [
    'norwegian' => [
        'country' => 'no',
    ],
    'eu' => [
        'continent' => 'eu',
        'isInEuropeanUnion' => true
    ],
    'europe' => [
        'continent' => 'eu',
    ],
    'us' => [
        'country' => 'us'
    ],    
    'global' => '*' 
]

The rules are parsed top to bottom, and the first match is used. So swapping the order of eu and europe i the above example would make every visitor from europe go to the site with handle europe.

If you don't add a site with a wildcard rule (ie 'global' => '*'), the visitor will not get redirected from the site they landed on if no other rule matched.

You can also use the detected browser language when setting up your rules:

'redirectMap' => [
    'norsk' => [
        'language' => 'no',
    ],
    'us' => [ // matches 'en-US'
        'language' => 'en',
        'languageRegion' => 'us',
    ],
    'canada' => [ // matches 'en-CA'
        'language' => 'en',
        'languageRegion' => 'ca',
    ],
    'english' => [ // matches all english language codes, 'en', 'en-US', 'en-NZ', etc.
        'language' => 'en',
    ],
]

You can even use combinations of geolocation and language information, although that might get a bit... edge-case:

/*
 * We have this very special site that we only want to redirect
 * people to if they're located in Norway, but have a browser
 * with jamaican english as their preferred language (yeah, our 
 * site is all about norwegian reggea and jerk chicken).
 */
'redirectMap' => [   
    'special' => [
        'country' => 'no',
        'language' => 'en',
        'languageRegion' => 'jm'
    ],
    'normal' => '*' 
]

The values in the redirect map can also be arrays:

'redirectMap' => [
    'scandinavia' => [
        'country' => ['no', 'se', 'dk', 'fi'],
    ],
    'europe' => [
        'continent' => 'eu',
    ],
    'global' => '*' 
]

Please note that this setting is not only used when autoRedirectEnabled is set to true, but also when you use craft.geomate.redirectInformation.

redirectMatchingElementOnly [bool]

Default: false
When set to true, matching based on the redirectMap will only happen if the request has a matched element, and that element is available in the matched site. When set to false, the user will be redirected to the root of the matched site, if a matching element could not be found.

redirectMapSimpleModeKey [string]

Default: 'country'
When using the simple syntax for redirectMap, by default it's assumed that the value is a country code. When set to 'language', it will instead be matched with accepted languages.

redirectIgnoreBots [bool]

Default: true
By default, bots will not be redirected. Disable this to also redirect bots (may impact SEO, so beware).

redirectIgnoreAdmins [bool]

Default: true
By default, admins will not be redirected. Disable this to also redirect admin users.

redirectIgnoreUserGroups [array]

Default: []
An array of user groups that should not be redirect. Example:

'redirectIgnoreUserGroups' => ['editors', 'subscribers'],

redirectIgnoreUrlPatterns [array]

Default: []
An array of url patterns that should not be redirect. The patterns can use regexp, and matches towards the full path of the request. To do an exact match, you can prefix the patter with =.

Example:

'redirectIgnoreUrlPatterns' => [
     // Matches '/robots.txt' directly
    '=/robots.txt', 

     // Matches anything that starts with '/dont-redirect/'
    '/^\/dont-redirect\//',

     //Matches a range of sitemap urls like '/sitemap.xml', '/no/sitemap.xml', '/sitemap_portfolio_1.xml', etc.
    '/^\/(no\/|en\/)*sitemap([\s\S])*\.xml$/',
],

redirectOverrideCookieName [string]

Default: 'GeoMateRedirectOverride'
Name of the cookie that registers if a user has overridden the preferred site (via a site switcher for instance).

cookieDuration [int]

Default: 43200
Duration of the cookies.

addGetParameterOnRedirect [bool]

Default: false
By default, a session (flash) variable is set when a user is redirected, which is picked up by GeoMate to detect if the user was redirected. In some cases, this is not ideal, for instance if the site is served through a front-side cache (Cloudflare, Varnish, or similar) and you want to notify the user about being redirected. By enabling this parameter, a query string will be appended to the URL instead.

redirectOverrideParam [string]

Default: '__geom'
Name of the query string parameter that is added to the URL if the user overrides site redirection.

redirectedParam [string]

Default: '__redir'
Name of the query string parameter that is added to the URL if the user is redirected (and addGetParameterOnRedirect is true).

paramValue [string]

Default: '✪'
Value of the query string parameters that GeoMate add.

forceIp [null|string]

Default: null
Force an IP to be used for geolocation lookup. In local environments, this needs to be set to a valid IP address for GeoMate to work, since your local IP won't return any results. Can also be used to debug IP's from different locations.

fallbackIp [null|string]

Default: null
You can supply a fallback IP that will be used if the supplied IP can't be found. It's probably a good idea to not use this, and instead implement some default functionality in your templates instead.

minimumAcceptLanguageQuality [int]

Default: 80
The Accept-Language header supplied by the browser may contain any number of languages, which all have a quality parameter (in this case, the range is from 0 to 100) that indicates how proficient the user is in these languages. This parameter indicates what quality level a language needs to have for GeoMate to consider it a valid language.


Template variables

craft.geomate.country([ip=null])

Returns country information in the form of a \GeoIp2\Model\Country model. If no information is found, null will be returned.

By default the IP address of the current request will be used, but you can also use the optional ip parameter to get information based on a specific IP.

craft.geomate.countryCode([ip=null])

Returns the two-character country code as a string. If no information is found, null will be returned.

By default the IP address of the current request will be used, but you can also use the optional ip parameter to get information based on a specific IP.

craft.geomate.city([ip=null])

Returns country information in the form of a \GeoIp2\Model\City model. If no information is found, null will be returned.

By default the IP address of the current request will be used, but you can also use the optional ip parameter to get information based on a specific IP.

craft.geomate.redirectInformation([ip=null])

Returns redirect information based on your redirect configuration as a RedirectInfo model. This information can be used to display information to the user about which site you think they should visit, and let them switch if they want. Example:

{% set redirectInfo = craft.geomate.redirectInformation() %}

{% if redirectInfo %}
    <div class="popup">
        <p>
            You are currently visiting our {{ currentSite.name }} site. 
            <a href="{{ redirectInfo.url | addOverrideParam }}">Click here</a> to go to our {{ redirectInfo.site.name }} site.
        </p>
    </div>
{% endif %}

By default the IP address of the current request will be used, but you can also use the optional ip parameter to get information based on a specific IP.

craft.geomate.isCrawler()

Returns true if the current request is from a crawler.

craft.geomate.isRedirected()

Returns true if the current request was redirected.

craft.geomate.isOverridden()

Returns true if the user has overridden the preferred site.

craft.geomate.getSiteLinks()

Returns an array of objects containing sites and redirect URLs for each of them. Useful for building site switchers, for instance like this:

{% set siteLinks = craft.geomate.getSiteLinks() %}
<nav>
    <ul>
        {% for siteLink in siteLinks %}
            <li><a href="{{ siteLink.url | addOverrideParam }}">{{ siteLink.site.name }}</a></li>
        {% endfor %}
    </ul>
</nav>

craft.geomate.getLanguages()

Return an array of AcceptedLanguage models, containing information about the users preferred browser languages.

{% set languages = craft.geomate.getLanguages() %}
{% for language in languages %}
    <p>
        Quality: {{ language.quality }}<br>
        Language: {{ language.language }}<br>
        Region: {{ language.region }}<br>
        Script: {{ language.script }}
    </p>
{% endfor %}

Twig filters

addOverrideParam

Adds the override param and value to an URL. You should always add this when linking between your sites, for instance in a site switcher.

addRedirectParam

Adds the redirect param and value to an URL. Not really that useful, but it's there. :)


Price, license and support

The plugin is released under the MIT license, meaning you can do what ever you want with it as long as you don't blame us. It's free, which means there is absolutely no support included, but you might get it anyway. Just post an issue here on github if you have one, and we'll see what we can do.

Changelog

See CHANGELOG.MD.

Credits

Brought to you by Værsågod

This product includes GeoLite2 data created by MaxMind, available from http://www.maxmind.com.

Icon designed by Freepik from Flaticon.