https://github.com/vaersaagod/geomate
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.
https://github.com/vaersaagod/geomate
craft-plugin craft3 craftcms geolocation language-detection
Last synced: 5 months ago
JSON representation
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.
- Host: GitHub
- URL: https://github.com/vaersaagod/geomate
- Owner: vaersaagod
- License: mit
- Created: 2018-08-29T08:53:40.000Z (almost 8 years ago)
- Default Branch: master
- Last Pushed: 2025-06-30T11:29:39.000Z (12 months ago)
- Last Synced: 2025-08-20T10:17:19.395Z (10 months ago)
- Topics: craft-plugin, craft3, craftcms, geolocation, language-detection
- Language: PHP
- Size: 131 KB
- Stars: 23
- Watchers: 3
- Forks: 12
- Open Issues: 5
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE.md
Awesome Lists containing this project
README
# 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.

## Requirements
This plugin requires Craft CMS 5.0 or later. The plugin also requires the zlib PHP extension.
### ⚠️ GeoMate and static caching
GeoMate relies on dynamic geolocation and IP-based logic in PHP, which makes the plugin generally incompatible with statically cached sites (e.g. those using full-page caching via Cloudflare, Craft Cloud, Servd and similar).
### ⚠️ GeoMate and Craft Cloud
GeoMate relies on a self-hosted IP geolocation database from MaxMind, which must be downloaded and stored locally. This makes it a bad fit for Craft Cloud or other hosting environments with ephemeral storage (e.g. serverless platforms or auto-scaling containers), where local files may be lost between requests or deployments.
## IMPORTANT UPDATE
As of December 30th 2019, the GeoLite2 databases are no longer publicly available
[due to compliance with GDPR and CCPA](https://blog.maxmind.com/2019/12/18/significant-changes-to-accessing-and-using-geolite2-databases/).
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"](https://github.com/vaersaagod/geomate#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](#configuring), and [download the geolocation database](#downloading-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](https://www.maxmind.com/en/geolite2/signup).
Once you have access to your users control panel, you need to [create a license key](https://www.maxmind.com/en/accounts/current/license-key).
Finally, you can get the download URL by [going to the direct download page](https://dev.maxmind.com/geoip/geoipupdate/#Direct_Downloads),
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](#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|string]
*Default: `43200`*
Duration of the cookies. Can be set to an integer or a valid PHP DateInterval string (e.g. `P1D`).
Setting the `cookieDuration` to `0` will create a session cookie.
### 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 %}
You are currently visiting our {{ currentSite.name }} site.
Click here to go to our {{ redirectInfo.site.name }} site.
{% 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() %}
- {{ siteLink.site.name }}
{% for siteLink in siteLinks %}
{% endfor %}
```
### 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 %}
Quality: {{ language.quality }}
Language: {{ language.language }}
Region: {{ language.region }}
Script: {{ language.script }}
{% 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](https://raw.githubusercontent.com/vaersaagod/geomate/master/CHANGELOG.md).
## Credits
Brought to you by [Værsågod](https://www.vaersaagod.no)
This product includes GeoLite2 data created by MaxMind, available from
[http://www.maxmind.com](http://www.maxmind.com).
Icon designed by [Freepik from Flaticon](https://www.flaticon.com/authors/freepik).