To be able to provide Geo personalisation, we need to determine where the visiting user is browsing from. The Geo location can be derived from the IP address of the user.
Options
There are a number of options available to convert the IP address of a user to a specific location.
- IP lookup services
The user’s browser (or the web server handling the user’s request, if not cached) can connect to one of many IP lookup services, which will provide location information based on the IP of the user.
The downside of this approach is that an extra request needs to be performed and this incurs delay. - IP Geolocation Database
There are databases of IP address to location which can be installed on the server.
These are large, need to be maintained and need to be run on the server. Not available for cached pages. - CDN - Man in the middle
CDNs, such as Cloudflare are able to apply logic on the edge and annotate the request.
Determining Geo location on the edge is efficient and easy and is what this article is going to cover.
Cloudflare Workers
Cloudflare offers a tool called Workers, which allows you to run code on the CDN. By the tool design, Workers have access to the browser request and therefore also to the client IP address.
Cloudflare is able to add geo data to the request or to its response and pass it through as a cookie or an extra header.
Setting it up
A "Cloudflare Worker" is code you write that runs on Cloudflare's edge. Your Worker will intercept all HTTP requests destined for your domain, and can return any valid HTTP response. Your worker can make outgoing HTTP requests to any server on the public internet. It can enrich requests, alter headers, redirect, enforce security, transform a response, rewrite links - you name it. You can write a whole application running as a Cloudflare Worker. All you need to start is a Cloudflare account.
Let’s have a look at the “Geolocation Hello World” code.
This Workers code processes the request, constructs a simple HTML page listing all the Geo location properties and sends it back to the client.
An example of the response:
Geolocation: Hello World! You now have access to geolocation data about where your user is visiting from. Colo: SYD Country: AU City: Sydney Continent: OC Latitude: -33.87150 Longitude: 151.20060 PostalCode: 2000 MetroCode: undefined Region: New South Wales RegionCode: NSW Timezone: Australia/Sydney
Example code for adding Geo data
Let’s say we don’t want the Workers to modify or generate any content. We want it to add Geo data to the HTTP responses, so the browser can use this information for Geo personalisation.
Here is a code which adds all the Geo properties Cloudflare provides as separate cookies. The client side code can then consume this information and personalise the content on the client’s side.
// Fetch the request and pass it through the function
addEventListener("fetch", event => {
event.respondWith(fetchAndApply(event.request))
})
async function fetchAndApply(request) {
// Store the response of the URL requested
let response = await fetch(request);
// Make sure we only modify text, not images.
let type = response.headers.get("Content-Type") || ""
if (!type.startsWith("text/html")) {
// Not text/hmlt. Don't modify.
return response
}
// Make the headers mutable by re-constructing the Response.
response = new Response(response.body, response);
const geo_properties = [
'asn',
'asOrganization',
'colo',
'country',
'isEUCountry',
'city',
'continent',
'latitude',
'longitude',
'metroCode',
'postalCode',
'region',
'regionCode',
'timezone',
];
const url = new URL(request.url);
const domain = request.headers.get('host');
geo_properties.forEach(property => {
let cookie_value = request.cf[property];
if(cookie_value) {
// Build the cooke string & append to response
a_cookie = `cp_${property}=${cookie_value}; path=/; domain=${domain}; secure; SameSite=None`;
response.headers.append('Set-Cookie', a_cookie);
}
});
// Return the response of the URL requested
// Maybe with an extra cookie
return response;
}
Handling the Geo information
The above example passes the Geo data in separate cookies, for the browser to use. We can have a script running in the browser modifying content based on the date in the cookies. Or we can map the geo data from the cookies to the browser’s local storage.
We now have a set of Geo data which can be used for personalisation. We could add a weather widget to the page, showing the local weather. We might use a background image with the theme of the city we are in. Or we can greet the page visitor with G’day if they are from Australia :-) Take a look at the intro text on Convivial Demo - the welcome message you see should be personalised to the country you are coming from.
How we use this with Drupal
At Morpht, we use the simple Cloudflare Workers code similar to the above to pass the Geo properties to the browser. We learnt this is a reliable and easy way of acquiring the Geo information, it is available from the moment the browser retrieves the first page, no extra lookup needed!
We then use a library called Convivial Profiler to map the Geo information to the local storage. With the foundations ready, we then use Drupal modules such as Personified to personalise the content. Of course, you could use any client side technology to handle the personalisation and it should be possible to use modules such as Smart Content and Personified directly on the values which are located in the cookie.
Conclusion
We have described a simple, reliable way of gathering geo information which can then be used for geo personalisation. The beauty is we leverage the tools available, without reinventing the wheel. Cloudflare has a suite of services which adds smarts. In this case, Cloudflare does the geo lookup for us on the edge and adds it to the server response, so the browser can use and store the info.
The end result is an efficient delivery of personalisation.