Sitecore GeoIP and Location Fallback Module. How it works.
What is GeoIP or IP Geolocation Service and why do we need it?
Sitecore GeoIP is a service which allows marketers and developers to retrieve a site visitor's current location. This location information can be used to set up personalization for different geographical regions and view reports pertinent to those locations.
Also, you can use Sitecore IP Geolocation to:
- Personalize site pages for visitors from different regions
- Fine tune tracking for Goals and Page events
- Define conditions in the automation of Engagement
- Geographically segmented contact lists
- See geolocation reports
- Find geolocation details in contact experience profiles
How does it work?
In general, IP Geolocation Service looks like a simple API which returns geolocation data. At least I personally thought so before I had a deeper look into it.
I used to think that it worked like on the image below:
I mistakenly believed that Sitecore takes the user's IP and simply sends it to the IP Geolocation Service which represents a web service. Mainly it is true. But there are several nuances associated with the data that was already resolved before.
So, here's how it works in real life:
Let’s analyze the process in detail. Sitecore always resolves the Geo Location data based on the IP address provided by user browser. When Sitecore received a request from the browser, first of all, it checks if the geodata has already been resolved for the current interaction (which actually is stored in the session). And if it has, this data will be returned. It is the most likely outcome for the second and subsequent requests. In case Geo data was not resolved for the current interaction before, Sitecore will try to retrieve it from application cache. Assuming that the data is there, it will be set for interaction and returned from resolving process. Application cache would contain it if someone with the same IP already visited the site. When the app cache doesn't contain necessary data for the requested IP, Sitecore will try to get it from xDB (from Mongo DB or MSSQL server). On condition xDB contains appropriate results, this data will be put in a cache and set for the current interaction. The case, when xDB contains the necessary data but cache does not, is possible when the data was resolved before but someone cleared the cache. After that, if we still don't retrieve the Geolocation, Sitecore will request it from GeoIP web service. Well, it looks good! We will get the data from the web service which is the last link in the call chain. Yes and no at the same time.
Actually, Sitecore requests the web service asynchronously and doesn’t wait while a result will be received. Main thread continues to process the request and load the page without Geo Location data. At the same time, when the asynchronous call is completed, the data will be put in the xDB, cache and set for interaction in a background thread. It causes an implicit issue for us because we don’t get a geodata for the first-page loading (request).
Basically, we can control the time, during which Sitecore should wait for the response from the web service and we can make him wait while the result will be received, but it can cause another issue for us - performance issue.
Perhaps it is not an unimportant issue, but I faced it when I had to implement a page redirection based on a visitor's current country.
When it became clear what the problem is, I started working on the solution.
I understand that we can’t wait for a result from the service. It means that we need to resolve the Geo Location data in some other way. I decided to use a local MaxMind database to resolve data for the first request and then update it with data from the web service as I consider it to be more accurate.
The most obvious solution was to extend a Lookup Provider (which is defined in the lookupManager in Sitecore.CES.GeoIp.config), where I was able to return the data from a local database and then update it with data from the web service. But I faced the problem again. When the lookup provider returns something, it is automatically put into xDB, cache and set for the interaction so the lookup provider will never be requested again for this IP address. Which means I don’t have an ability to update this data with more accurate data from the service.
The process of geo data resolving happens in Sitecore.Analytics.Lookups.GeoIpManager. It is a static class which we are also not able to override.
I've spent a lot of time, but the necessary solution has been found. I created the Sitecore module available at the Marketplace and released the code in the GitHub: The GeoIP Fallback is a simple module that improves a current location resolving process with additional ability to fake your current location. Feel free to try it and share if you find it useful.