Blog

EdgeWorkers Use Case: Fast Geolocation

June 11, 2020 · by Josh Johnson and Javier Garza ·

Many websites use geolocation intelligence to improve the user experience for online visitors. Geolocation allows you to increase user engagement, reduce bounce rate, and improve conversions by delivering location-specific content to visitors such as localized site versions, nearby stores, or special products and offers. There are two different methods for performing geolocation: Browser location API or IP address intelligence. 

Browser location API delivers a very accurate location using GPS and other sensor data on mobile devices. However, this method requires the user to allow access to their exact location, which many are reluctant to provide. Additionally, use of the browser’s location services for high-accuracy geolocation can be slow since the device takes time to acquire a GPS signal.

IP address intelligence uses a database to map the user’s IP address to location information without requiring user permission. However, it is less accurate than the browser location API on mobile connections, showing the location of the service provider’s mobile gateway, which may be far away from the user. 

In this article, we will focus on IP intelligence to provide geolocation data. IP-based geolocation can be used on its own, or to complement the browser’s location API. If a user does not allow their exact location through the browser’s API, then an IP address can be used as a fallback. 

EdgeScape and EdgeWorkers

IP-based geolocation is often implemented as a separate HTTP request, allowing static page content to remain cacheable with client-side logic to handle the dynamic response to the user’s location. Additional HTTP requests to a geolocation service can decrease page load speed and increase visitor frustration, but Akamai EdgeScape and EdgeWorkers together perform IP-based geolocation quickly at the Edge.

Akamai EdgeScape provides detailed information about a user’s location based on IP address including the user’s country, state, county, city, zip code, designated market area (DMA), metropolitan statistical area (MSA), and several other attributes. This data can be used at the Edge as well as forwarded to the origin server. EdgeScape can also be installed as a standalone geolocation database to implement custom business logic on-premise via a server of your choice or in a cloud provider like Amazon Web Services (AWS).

The Akamai EdgeWorkers service executes custom JavaScript logic at the Edge of the Internet. Combining EdgeWorkers JavaScript execution with EdgeScape augments location data with custom data, allowing the geolocation and custom data to be added to the page without requiring additional HTTP requests from the browser. This approach provides the benefits of geolocation without the performance hit from using a separate service.

In the example below, we will retrieve the current user’s location from EdgeScape, determine which sales region the customer is located in, and add a cookie with the user’s location, region, and total population of the region. The dynamic data will be added to a cookie, even on cached pages. Adding the cookie at the Edge, rather than the origin, reduces latency and improves performance.

Implementation steps

Adding an EdgeWorker is a simple process:

  1. Create the EdgeWorkers code bundle

  2. Upload/activate the code bundle to the Akamai Edge

  3. Add the EdgeWorker to your Akamai property configuration

Create the EdgeWorkers code bundle

There are four distinct phases of a request lifecycle where a JavaScript function can be executed, providing access to inspect and modify requests and responses:

1. Client request executed on every request before checking to see if content is available in the cache

2. Origin request executed on uncached requests before going forward to the origin

3. Origin response executed after the origin responds

4. Client response executed prior to responding to the client

client to origin

To send geolocation data to the browser, we can add a cookie in the client response phase with the user’s location data. Inserting the cookie directly with the page response allows us to avoid making a separate network request, improving page load performance.

Following is an example of the code to set geolocation data in a response cookie — it could be easily extended to implement additional custom business logic:

// main.js

// Import cookies library to provide helper functions

import {SetCookie} from 'cookies';

import {salesRegions} from 'data.js';

 

function findRegionByState (state) {

  return salesRegions.find((region) => region.states.includes(state));

}

 

// Add cookie in the outgoing response to the browser

export function onClientResponse(request, response) {

  // Retrieve user location from the request object

  const userLocation = request.userLocation;

 

  // Extract country, region (e.g., U.S. state), and city from userLocation

  const country = userLocation.country || "N/A";

  const region = userLocation.region || "N/A";

  const city = userLocation.city || "N/A";

  const salesRegion = findRegionByState(region);

 

  // Create a cookie, with location fields separate by '+'

  const locationCookieValue = `${country}+${region}+${city}`;

 

  // Create cookie with an expiration of 1 day (86,400 seconds)

  var cookie = new SetCookie({

    name: 'location',

    value: locationCookieValue,

    path: '/',

    maxAge: 86400

  });

 

  // Add cookie header to outgoing  response

  response.setHeader('Set-Cookie', cookie.toHeader());

 

  if (salesRegion) {

    const regionDataCookieValue = `${salesRegion.name}:${salesRegion.population}`;

    var salesRegionCookie = new SetCookie({

      name: 'salesRegion',

      value: regionDataCookieValue,

      path: '/',

      maxAge: 86400

    });

    response.setHeader('Set-Cookie', salesRegionCookie.toHeader());

  }

}

The sales region data, including a list of states and 2019 population data, is exported from a separate JavaScript file:

//data.js

//2019 Population data from https://www.census.gov/popclock/print.php?component=growth&image=//www.census.gov/popclock/share/images/growth_1561939200.png

let salesRegions = [

  {

    name: "Northeast",

    states: ["CT", "MA", "ME", "NH", "NJ", "NY", "PA", "RI", "VT"],

    population: 55982803

  },

  {

    states: ["IA", "IL", "IN", "KS", "MI", "MN", "MO", "ND", "NE", "OH", "SD", "WI"],

    population: 68329004

  },

  {

    states: ["AL", "AR", "DC", "DE", "GA", "FL", "KY", "LA", "MD", "MS", "NC", "OK", "SC", "TN", "TX", "VA", "WV"],

    population: 125580448

  },

  {

    states: ["AK", "AZ", "CA", "CO", "HI", "ID", "MT", "NM", "NV", "OR", "UT", "WA", "WY"],

    population: 78347268

  }

];

 

export {salesRegions};

This code and the associated bundle.json file can be packaged into a code bundle with a simple command:

tar -cvzf geolocation.tgz bundle.json main.js data.js

Upload/activate code bundle 

You can upload and activate an EdgeWorkers code bundle using the Akamai control center graphical user interface (GUI) or via API. To use the GUI:

  • Login to control.akamai.com, and go to “Edge functions”

  • Create a new EdgeWorker ID, and provide a name and group

  • Click on the newly created EdgeWorker, create a new version, and upload the code bundle (the geolocation.tgz file created in the previous step)

  • Activate the version to the Akamai staging and production networks

Alternatively, you can run a few API calls:

  1. Create an EdgeWorker ID by creating a JSON request body that includes the groupId and a name, and then make an API POST call to “/edgeworkers/v1/ids” which will return a JSON response that includes the id as the integer following the “edgeWorkerId” field

  2. Create a new version of the EdgeWorker by making a POST request to “/edgeworkers/v1/ids/{edgeWorkerId}/versions” (replace “edgeWorkerId” with the integer number you got on the previous call) and reference the “.tgz” packaged bundle we created earlier in the body of the POST request — the above call (if successful) should return the version number of the EdgeWorker which is an auto-incremented integer starting with “1”

  3. Activate the EdgeWorker by making a POST request to “/edgeworkers/v1/ids/{edgeWorkerId}/activations” and indicating the version of the EdgeWorker you want to activate (for example, “1”) as well as the desired network (staging or production)

See the EdgeWorkers API Getting Started Guide for more details.

Configure Akamai property

To associate the EdgeWorker with the property, add the “EdgeWorkers” behavior and select the Identifier corresponding to the EdgeWorker that you created in the previous step. Add a match condition to avoid executing the EdgeWorker if the location cookie has already been set. Finally, save and activate the new property version.

Request Cookie

Note: You can also add the EdgeWorkers behavior to the property using the Property Manager API or the property manager command-line interface (CLI). 

Testing

To test the EdgeWorker, simply navigate to the page and observe that the location cookie is sent to the browser. Once the cookie exists, it will not be sent again to the browser on subsequent requests.

You can see an example of EdgeWorkers in action at https://edgeworkers.akamaideveloper.com/geo-location/.

Learn more

Here are great resources to learn more:

About the authors

josh

Josh Johnson is an Enterprise Architect at Akamai Technologies where he consults with enterprise customers, enabling development teams to design web applications for performance, security, and reliability. As a DevOps advocate, Josh helps organizations improve quality and efficiency through automation. His experience ranges from small startups to large multi-national corporations. Outside of work, he has mentored competitive and educational robotics teams with students from Kindergarten through 12th grade.

Javier

Javier Garza is a developer evangelist at Akamai Technologies where he helps the largest companies on the internet run fast and secure apps by leveraging web performance, security and DevOps best practices. Javier has written many articles on HTTP/2 and web performance, and is the co-author of the O’Reilly Book “Learning HTTP/2”. In 2018, Javier spoke at more than 20 developer-related events around the world, including well-known conferences like Velocity, AWS Re:Invent, and PerfMatters. His life’s motto is: share what you learn, and learn what you don’t. In his free time he enjoys challenging workouts and volunteering for non-profits in areas like children and education