{"id":36970785,"url":"https://github.com/vaersaagod/geomate","last_synced_at":"2026-01-13T21:50:30.394Z","repository":{"id":48561713,"uuid":"146572703","full_name":"vaersaagod/geomate","owner":"vaersaagod","description":"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.","archived":false,"fork":false,"pushed_at":"2025-06-30T11:29:39.000Z","size":134,"stargazers_count":23,"open_issues_count":5,"forks_count":12,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-08-20T10:17:19.395Z","etag":null,"topics":["craft-plugin","craft3","craftcms","geolocation","language-detection"],"latest_commit_sha":null,"homepage":null,"language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/vaersaagod.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2018-08-29T08:53:40.000Z","updated_at":"2025-06-17T10:41:18.000Z","dependencies_parsed_at":"2023-02-14T07:01:29.497Z","dependency_job_id":"61e57542-01c5-48b1-ba88-f01c3af957f9","html_url":"https://github.com/vaersaagod/geomate","commit_stats":{"total_commits":47,"total_committers":5,"mean_commits":9.4,"dds":0.3191489361702128,"last_synced_commit":"bd5992c6e97bb0d1ce45fca742921012fd7b015e"},"previous_names":[],"tags_count":26,"template":false,"template_full_name":null,"purl":"pkg:github/vaersaagod/geomate","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vaersaagod%2Fgeomate","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vaersaagod%2Fgeomate/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vaersaagod%2Fgeomate/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vaersaagod%2Fgeomate/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/vaersaagod","download_url":"https://codeload.github.com/vaersaagod/geomate/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vaersaagod%2Fgeomate/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28401059,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-13T14:36:09.778Z","status":"ssl_error","status_checked_at":"2026-01-13T14:35:19.697Z","response_time":56,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["craft-plugin","craft3","craftcms","geolocation","language-detection"],"created_at":"2026-01-13T21:50:29.752Z","updated_at":"2026-01-13T21:50:30.389Z","avatar_url":"https://github.com/vaersaagod.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"# GeoMate plugin for Craft CMS 5.x\n\nGeoMate is a friend in need for all things geolocation. IP to geo lookup, automatic \nredirects (based on country, continent, language, etc), site switcher... You name it.  \n\n![GeoMate logo](resources/img/plugin-logo.png)\n\n## Requirements\n\nThis plugin requires Craft CMS 5.0 or later. The plugin also requires the zlib PHP extension.  \n\n### ⚠️ GeoMate and static caching\n\nGeoMate 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).\n\n### ⚠️ GeoMate and Craft Cloud\n\nGeoMate 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.\n\n## IMPORTANT UPDATE\n\nAs of December 30th 2019, the GeoLite2 databases are no longer publicly available\n[due to compliance with GDPR and CCPA](https://blog.maxmind.com/2019/12/18/significant-changes-to-accessing-and-using-geolite2-databases/).\nPreviously, the public URLs for these databases were set as defaults in the GeoMate\nconfiguration. As of GeoMate 1.1.0, these have been removed, and\nyou now need to register a maxmind account, get a license key, and configure the download \nURLs yourself. See the [\"Downloading the geolocation database\"](https://github.com/vaersaagod/geomate#downloading-the-geolocation-database) \nbelow for more info on how to do this.\n\nAs before, you can also download the database manually and put it in your `dbPath` yourself. \n\n## Installation\n\nTo install the plugin, either install it from the plugin store, or follow these instructions:\n\n1. Install with composer via `composer require vaersaagod/geomate` from your project directory.\n2. Install the plugin in the Craft Control Panel under Settings → Plugins, or from the command line via `./craft install/plugin geomate`.\n3. For GeoMate to do anything, you need to [configure it](#configuring), and [download the geolocation database](#downloading-the-geolocation-database).\n\n---\n\n## GeoMate Overview\n\nGeoMate helps you detect the location and language preferences of you visitors, and lets you set up\nfine-grained rules to help you redirect users to the correct site, or show location/language specific \ninformation in your templates.\n\nGeoMate relies on self-hosted Maxmind GeoIP2 databases for geolocation, and no external services \nare needed to look up IP information. By default GeoMate use the free Maxmind GeoLite2\ndatabase, but can easily be configured to use commercial versions of the database as long as it's \nin the MaxMind DB file format. \n\n---\n\n## Downloading the geolocation database\n\nFor GeoMate to be able to get information about an IP address, you need to download\na GeoIP2 database. The easiest way to get one, is to use Maxmind's free GeoLite2\ndatabase. For better results and more frequent updates, you should consider their \ncommercial alternatives.\n\nTo get the GeoLite2 database, you first need to [sign up for an account at Maxmind](https://www.maxmind.com/en/geolite2/signup).\nOnce you have access to your users control panel, you need to [create a license key](https://www.maxmind.com/en/accounts/current/license-key).\nFinally, you can get the download URL by [going to the direct download page](https://dev.maxmind.com/geoip/geoipupdate/#Direct_Downloads),\nand let GeoMate know about them by setting the `countryDbDownloadUrl` and `cityDbDownloadUrl` config settings\naccordingly. At the time of writing, the URLs should be (replace `YOUR_LICENSE_KEY` with your license key):    \n\n```\n'countryDbDownloadUrl' =\u003e 'https://download.maxmind.com/app/geoip_download?edition_id=GeoLite2-Country\u0026license_key=YOUR_LICENSE_KEY\u0026suffix=tar.gz',\n'cityDbDownloadUrl' =\u003e 'https://download.maxmind.com/app/geoip_download?edition_id=GeoLite2-City\u0026license_key=YOUR_LICENSE_KEY\u0026suffix=tar.gz',\n```\n\n_Please note, although this is the recommended approach, you can also just download the files\nmanually, or through some other mechanism, and put them in the `dbPath` yourself._  \n\nGeoMate comes with a handy utility that helps you download the database. You can\naccess it by going to Utilities \u003e GeoMate from the control panel main menu. Please check that the \nsettings is as desired, and download the databases by clicking the \"Update now\" button.\n\nYou can also download the database by accessing the `geomate/database/update-database` controller \naction directly, or set up a cron job that hits it at regular intervals. The action URL for your \ninstallation is shown in the utility.\n\n---\n\n## Using GeoMate\n\nYou can get information about the user's location through the `craft.geomate.country`, `craft.geomate.countryCode`\nand `craft.geomate.city` [template variables](#template-variables). \n\nBy configuring the `redirectMap` config setting, you can define the rules for what location\nor language information is required for each of your sites. If you want to automatically redirect your users\nto the appropriate site, you can enable the `autoRedirectEnabled` config setting, or you can use the \n`craft.geomate.redirectInformation` template variable to get the information inside your templates, \nand display a banner or popup to trigger the user to switch site.\n\nGeoMate also provides a helper to build a site switcher, the `craft.geomate.getSiteLinks` template variable, \nand some twig functions, `addOverrideParam` and `addRedirectParam`, to add the necessary parameters to ensure \nthat GeoMate picks up that the user has selected a specific site.\n\nThere's quite a few config settings that can be used to tweak stuff, so make sure you read through\nit to get an idea of what the defaults are, and how you can use them to your needs.\n\n_When working locally, you need to override the IP by using the `forceIp` config setting for\nGeoMate to do anything useful (since it would try to look up 127.0.0.1 if you didn't, and\nthat won't return any results)._\n\n---\n\n## Configuring\n\nGeoMate can be configured by creating a file named `geomate.php` in your Craft config folder, \nand overriding settings as needed. \n\n### cacheEnabled [bool]\n*Default: `true`*  \nEnables or disables caching of IP data.\n\n### cacheDuration [string|int]\n*Default: `'P7D'`*  \nDuration that looked up IP data should be cached, set as a date interval string or an int indicating the number of seconds.\n\n### useSeparateLogfile [bool]\n*Default: `true`*  \nWhen enabled, GeoMate will create and use its own log file named `geomate.log` in Craft's log path.\n\n### logLevel [int]\n*Default: `\\yii\\log\\Logger::LEVEL_ERROR`*  \nWhen using GeoMate's log file (ie `useSeparateLogfile` being set to `true`), you can specify what log levels\nshould be logged. By default, only errors will be logged, but if you set it to `\\yii\\log\\Logger::LEVEL_WARNING` \nor  `\\yii\\log\\Logger::LEVEL_INFO` you'll get more information. \n\n### dbPath [string]\n*Default: `''`*  \nPath to GeoIP databases. If none is given (default), the database will be\nstored in `/storage/geomate` or whichever path is defined as Craft's storage path. \n\n### countryDbFilename [string]\n*Default: `'GeoLite2-Country.mmdb'`*  \nFile name of the GeoIP _country_ database.\n\n### cityDbFilename [string]\n*Default: `'GeoLite2-City.mmdb'`*  \nFile name of the GeoIP _city_ database.\n\n### countryDbDownloadUrl [string|null]\n*Default: `null`*  \nDownload URL for the GeoIP _country_ database.\n\n### cityDbDownloadUrl [string|null]\n*Default: `null`*  \nDownload URL for the GeoIP _city_ database.\n\n### downloadDbIfMissing [bool]\n*Default: `false`*  \nIf a given database is missing when GeoMate tries to do an IP lookup, it'll \nfail silently, log the error, and not do a redirect or return any redirect information. \nIf you enable this setting, GeoMate will try to download and unpack the database\nif it is missing. \n\nMake sure you're certain that download works before enabling this. If something goes \nwrong during the download, GeoMate will continue to try on every request, which could \ntake up alot of resources depending on what fails.  \n\n### autoRedirectEnabled [bool]\n*Default: `false`*  \nSet this to `true` to enable automatic redirects of users to sites based on the `redirectMap` config setting.\n\n### autoRedirectExclude [array]\n*Default: `[]`*  \nA list of site handles that should be excluded from automatic redirects.\n\n### redirectMap [array]\n*Default: `[]`*  \nThis powerful config setting enables you to create detailed rules for redirecting users to \nyour different sites, based on detected information about location or language.\n\nThe easiest way to use this setting is to map site handles to country codes:\n\n``` \n'redirectMap' =\u003e [\n    'norwegian' =\u003e 'no',\n    'swedish' =\u003e 'se',\n    'global' =\u003e '*' \n]\n```\n\nIn this example, there are three sites with handles `norwegian`, `swedish` and `global`. Visitors\nfrom Norway is redirected to the norwegian site, visitors from Sweden are redirected to the\nswedish site, and the rest is sent to the global site.\n\nBy default, it's assumed that the value is the detected country code. If `redirectMapSimpleModeKey`\nis set to `language` though, the users browser language is used.\n\nBut, you can also use more advanced rules:\n\n```\n'redirectMap' =\u003e [\n    'norwegian' =\u003e [\n        'country' =\u003e 'no',\n    ],\n    'eu' =\u003e [\n        'continent' =\u003e 'eu',\n        'isInEuropeanUnion' =\u003e true\n    ],\n    'europe' =\u003e [\n        'continent' =\u003e 'eu',\n    ],\n    'us' =\u003e [\n        'country' =\u003e 'us'\n    ],    \n    'global' =\u003e '*' \n]\n```\n\nThe rules are parsed top to bottom, and _the first match is used_. So swapping the order of \n`eu` and `europe` i the above example would make every visitor from europe go to the site\nwith handle `europe`.\n\nIf you don't add a site with a wildcard rule (ie `'global' =\u003e '*'`), _the visitor will not\nget redirected from the site they landed on if no other rule matched_. \n\nYou can also use the detected browser language when setting up your rules:\n\n```\n'redirectMap' =\u003e [\n    'norsk' =\u003e [\n        'language' =\u003e 'no',\n    ],\n    'us' =\u003e [ // matches 'en-US'\n        'language' =\u003e 'en',\n        'languageRegion' =\u003e 'us',\n    ],\n    'canada' =\u003e [ // matches 'en-CA'\n        'language' =\u003e 'en',\n        'languageRegion' =\u003e 'ca',\n    ],\n    'english' =\u003e [ // matches all english language codes, 'en', 'en-US', 'en-NZ', etc.\n        'language' =\u003e 'en',\n    ],\n]\n```\n  \nYou can even use combinations of geolocation and language information, although \nthat might get a bit... edge-case:\n\n``` \n/*\n * We have this very special site that we only want to redirect\n * people to if they're located in Norway, but have a browser\n * with jamaican english as their preferred language (yeah, our \n * site is all about norwegian reggea and jerk chicken).\n */\n'redirectMap' =\u003e [   \n    'special' =\u003e [\n        'country' =\u003e 'no',\n        'language' =\u003e 'en',\n        'languageRegion' =\u003e 'jm'\n    ],\n    'normal' =\u003e '*' \n]\n```\n\nThe values in the redirect map can also be arrays:\n\n```\n'redirectMap' =\u003e [\n    'scandinavia' =\u003e [\n        'country' =\u003e ['no', 'se', 'dk', 'fi'],\n    ],\n    'europe' =\u003e [\n        'continent' =\u003e 'eu',\n    ],\n    'global' =\u003e '*' \n]\n```\n\nPlease note that this setting is not only used when `autoRedirectEnabled` is set to `true`, but also\nwhen you use `craft.geomate.redirectInformation`. \n\n### redirectMatchingElementOnly [bool]\n*Default: `false`*  \nWhen set to `true`, matching based on the `redirectMap` will only happen if the request has\na matched element, and that element is available in the matched site. When set to `false`, the\nuser will be redirected to the root of the matched site, if a matching element could not be \nfound.\n\n### redirectMapSimpleModeKey [string]\n*Default: `'country'`*  \nWhen using the simple syntax for `redirectMap`, by default it's assumed that the value is a \ncountry code. When set to `'language'`, it will instead be matched with accepted languages.   \n\n### redirectIgnoreBots [bool]\n*Default: `true`*  \nBy default, bots will not be redirected. Disable this to also redirect bots (may impact SEO, so beware).\n\n### redirectIgnoreAdmins [bool]\n*Default: `true`*  \nBy default, admins will not be redirected. Disable this to also redirect admin users. \n\n### redirectIgnoreUserGroups [array]\n*Default: `[]`*  \nAn array of user groups that should not be redirect. Example:\n\n```\n'redirectIgnoreUserGroups' =\u003e ['editors', 'subscribers'],\n``` \n\n### redirectIgnoreUrlPatterns [array]\n*Default: `[]`*  \nAn array of url patterns that should not be redirect. The patterns can use regexp, and matches \ntowards the full path of the request. To do an exact match, you can prefix the patter with `=`. \n\nExample:\n\n```\n'redirectIgnoreUrlPatterns' =\u003e [\n     // Matches '/robots.txt' directly\n    '=/robots.txt', \n\n     // Matches anything that starts with '/dont-redirect/'\n    '/^\\/dont-redirect\\//',\n\n     //Matches a range of sitemap urls like '/sitemap.xml', '/no/sitemap.xml', '/sitemap_portfolio_1.xml', etc.\n    '/^\\/(no\\/|en\\/)*sitemap([\\s\\S])*\\.xml$/',\n],\n```\n\n### redirectOverrideCookieName [string]\n*Default: `'GeoMateRedirectOverride'`*  \nName of the cookie that registers if a user has overridden the preferred site (via a site switcher \nfor instance).\n\n### cookieDuration [int|string]\n*Default: `43200`*  \nDuration of the cookies. Can be set to an integer or a valid PHP DateInterval string (e.g. `P1D`).  \nSetting the `cookieDuration` to `0` will create a session cookie.\n\n### addGetParameterOnRedirect [bool]\n*Default: `false`*  \nBy default, a session (flash) variable is set when a user is redirected, which is picked up by\nGeoMate to detect if the user was redirected. In some cases, this is not ideal, for instance if \nthe site is served through a front-side cache (Cloudflare, Varnish, or similar) and you want to\nnotify the user about being redirected. By enabling this parameter, a query string will be appended\nto the URL instead.\n\n### redirectOverrideParam [string]\n*Default: `'__geom'`*  \nName of the query string parameter that is added to the URL if the user overrides site redirection. \n\n### redirectedParam [string]\n*Default: `'__redir'`*  \nName of the query string parameter that is added to the URL if the user is redirected \n(and `addGetParameterOnRedirect` is `true`). \n\n### paramValue [string]\n*Default: `'✪'`*  \nValue of the query string parameters that GeoMate add.\n\n### forceIp [null|string]\n*Default: `null`*  \nForce an IP to be used for geolocation lookup. In local environments, this needs to be set to a \nvalid IP address for GeoMate to work, since your local IP won't return any results. Can also be used\nto debug IP's from different locations.  \n\n### fallbackIp [null|string]\n*Default: `null`*  \nYou can supply a fallback IP that will be used if the supplied IP can't be found. It's probably a good\nidea to _not_ use this, and instead implement some default functionality in your templates instead. \n\n### minimumAcceptLanguageQuality [int]\n*Default: `80`*  \nThe `Accept-Language` header supplied by the browser may contain any number of languages, which all \nhave a quality parameter (in this case, the range is from 0 to 100) that indicates how proficient \nthe user is in these languages. This parameter indicates what quality level a language needs to have \nfor GeoMate to consider it a valid language.  \n\n---\n\n## Template variables\n\n### craft.geomate.country([ip=null])\nReturns country information in the form of a `\\GeoIp2\\Model\\Country` model. If no information is \nfound, `null` will be returned.\n\n_By default the IP address of the current request will be used, but you can also use the optional ip \nparameter to get information based on a specific IP._\n\n### craft.geomate.countryCode([ip=null])\nReturns the two-character country code as a `string`. If no information is found, `null` will be returned.\n\n_By default the IP address of the current request will be used, but you can also use the optional ip \nparameter to get information based on a specific IP._\n\n### craft.geomate.city([ip=null])\nReturns country information in the form of a `\\GeoIp2\\Model\\City` model. If no information is \nfound, `null` will be returned.\n\n_By default the IP address of the current request will be used, but you can also use the optional ip \nparameter to get information based on a specific IP._\n\n### craft.geomate.redirectInformation([ip=null])\nReturns redirect information based on your redirect configuration as a RedirectInfo model. This\ninformation can be used to display information to the user about which site you think they should\nvisit, and let them switch if they want. Example:\n\n```\n{% set redirectInfo = craft.geomate.redirectInformation() %}\n\n{% if redirectInfo %}\n    \u003cdiv class=\"popup\"\u003e\n        \u003cp\u003e\n            You are currently visiting our {{ currentSite.name }} site. \n            \u003ca href=\"{{ redirectInfo.url | addOverrideParam }}\"\u003eClick here\u003c/a\u003e to go to our {{ redirectInfo.site.name }} site.\n        \u003c/p\u003e\n    \u003c/div\u003e\n{% endif %}\n```  \n\n_By default the IP address of the current request will be used, but you can also use the optional ip \nparameter to get information based on a specific IP._\n\n### craft.geomate.isCrawler()\nReturns `true` if the current request is from a crawler.\n\n### craft.geomate.isRedirected()\nReturns `true` if the current request was redirected.\n\n### craft.geomate.isOverridden()\nReturns `true` if the user has overridden the preferred site.\n\n### craft.geomate.getSiteLinks()\nReturns an array of objects containing sites and redirect URLs for each of them. Useful for\nbuilding site switchers, for instance like this:\n\n```\n{% set siteLinks = craft.geomate.getSiteLinks() %}\n\u003cnav\u003e\n    \u003cul\u003e\n        {% for siteLink in siteLinks %}\n            \u003cli\u003e\u003ca href=\"{{ siteLink.url | addOverrideParam }}\"\u003e{{ siteLink.site.name }}\u003c/a\u003e\u003c/li\u003e\n        {% endfor %}\n    \u003c/ul\u003e\n\u003c/nav\u003e\n```\n\n### craft.geomate.getLanguages()\nReturn an array of AcceptedLanguage models, containing information about the users preferred \nbrowser languages. \n\n```\n{% set languages = craft.geomate.getLanguages() %}\n{% for language in languages %}\n    \u003cp\u003e\n        Quality: {{ language.quality }}\u003cbr\u003e\n        Language: {{ language.language }}\u003cbr\u003e\n        Region: {{ language.region }}\u003cbr\u003e\n        Script: {{ language.script }}\n    \u003c/p\u003e\n{% endfor %}\n```\n\n---\n\n## Twig filters\n\n### addOverrideParam\nAdds the override param and value to an URL. \n*You should always add this when linking between your sites, for instance in a site switcher*.\n\n### addRedirectParam\nAdds the redirect param and value to an URL. Not really that useful, but it's there. :)\n\n---\n\n## Price, license and support\n\nThe plugin is released under the MIT license, meaning you can do what ever you want with it as long \nas you don't blame us. **It's free**, which means there is absolutely no support included, but you \nmight get it anyway. Just post an issue here on github if you have one, and we'll see what we can do. \n\n## Changelog\n\nSee [CHANGELOG.MD](https://raw.githubusercontent.com/vaersaagod/geomate/master/CHANGELOG.md).\n\n## Credits\n\nBrought to you by [Værsågod](https://www.vaersaagod.no)\n\nThis product includes GeoLite2 data created by MaxMind, available from\n[http://www.maxmind.com](http://www.maxmind.com).\n\nIcon designed by [Freepik from Flaticon](https://www.flaticon.com/authors/freepik).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvaersaagod%2Fgeomate","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fvaersaagod%2Fgeomate","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvaersaagod%2Fgeomate/lists"}