Easy Geo-Targeting with an Edge App

By Elise 

Geo-targeting enables web applications to use visitors’ geographical location (country or city based on IP) to serve tailored content. IP addresses can be found using a number of methods; one of which will be implemented in some example apps below.  Once an IP address is obtained, country, city, region, zip code, coordinates and more can all be found. Then you can serendipitously deliver the right message to the right place.

Serving responses to users based on their location is a method that’s been around for a while. However, what’s new and intriguing about it is its effectiveness in “location-based marketing”, as well as the realization that anyone can do it. Lately, brands and businesses have recognized geo-targeting as a simple way to find new customers. It’s also popular for:

Some examples of what you can do with a geo-targeting application includes:

Geo-Targeting with an Edge App

Backstory: CDNs (content delivery networks) are networks of servers in distributed locations, called “Edge servers”. When someone makes a request, the server closest to them will return the cached data. If the CDN doesn’t have the data, further requests are made to the backend and database.

Fly is a global JavaScript runtime that gives the developer the ability to build a CDN. The neat thing about a Fly Edge App is that you can implement geo-targeting to cache personalization data on servers that are geographically close to individual users. This gives you the benefits of geo-targeting and speed.

For example, if there’s a nearby office building that you know the IP address of, you can easily write an Edge App that checks if the request is coming from that building. If it is, you can send them a specific ad campaign that you want only them to see. Additionally, you can cache responses on Edge servers to speed up requests so content is delivered quicker in the future. The example below shows how to do this with an Edge App.

import { responseCache } from '@fly/cache'

fly.http.respondWith( async function(req) {
  // find your visitor's IP address
  let response = await fetch("https://ipinfo.io")
  let json = await response.json()

  // add ip header to your requests
  req.headers.set("Fly-IP", json.ip)
  let ip = req.headers.get("Fly-IP")

  // use this header to change behavior based on ip address
  // show visitor special ad campaign if IP address is a match
  if (ip == "198.51.100.0/24") {
    let cache = await responseCache.get("key")

    // serve cached response if there is one
    if (cache) {
      return cache
    }

    // if there is nothing cached, create a response by fetching the site + campaign you want to show
    // and then store the response in the cache for the future
    let response = await fetch("https://www.mysite.com?campaign=special")
    await responseCache.set("key", response)
    return response
  } else { 
    // show visitor standard ad campign if IP doesn't match
    let cache = await responseCache.get("key")

    // serve cached response if there is one
    if (cache) {
      return cache
    }

    // if there is nothing cached, create a response by fetching the site + campaign you want to show
    // and then store the response in the cache for the future
    let response = await fetch("https://www.mysite.com?campaign=standard")
    await responseCache.set("key", response)
    return response
  }
})

This example uses "ipinfo.io" (an online source that allows you to pinpoint your users’ locations to customize their experiences) to get visitor location information in json format. First, we’re finding your visitor's IP address and setting it as a header (under Fly-IP) for requests. Then we’re checking if the request’s IP address matches the IP address that we want to send a special response to. If it does, we’ll check Fly’s global cache for a previously fetched response. If there’s a response already in the cache, serve that to the visitor. If not, we’ll create a response by fetching your app with the special campaign you want to deliver to this IP. Then set it in the cache for faster response times in the future (take note that you should create a unique cache "key" in your own app). Finally, if the IP address does not match that of which you are wanting to send a special response to, simply serve the user your standard ad campaign (while also getting + setting the response in the cache).

Target, Attract and Grow

You can target entire countries that are relevant to your application. For example, when selling products, tailor your message to audiences in different countries by advertising your worldwide shipping or international offerings. Or simply serve them a version of your site in their language. Take a look at the example below that illustrates this:

import { responseCache } from '@fly/cache'

fly.http.respondWith( async function(req) {
  // detect your visitor's geographic location based on their IP address
  let response = await fetch("https://ipinfo.io")
  let json = await response.json()

  // add location headers to your requests
  req.headers.set("Fly-IP-Country", json.country)
  let country = req.headers.get("Fly-IP-Country")

  req.headers.set("Fly-IP-City", json.city)
  let city = req.headers.get("Fly-IP-City")

  req.headers.set("Fly-IP-Region", json.region)
  let region = req.headers.get("Fly-IP-Region")

  // use these headers to change behavior based on user geography
  // send visitor to United States Amazon site
  if (country == "US") {
    let x = handleCountry("https://www.amazon.com/")
    return x
  }
  // send visitor to Germany Amazon site
  if (country == "DE") {
    let x = handleCountry("https://www.amazon.de/")
    return x
  }
  // send visitor to China Amazon site
  if (country == "CN") {
    let x = handleCountry("https://www.amazon.cn/")
    return x
  }
  // send visitor to Mexico Amazon site
  if (country == "MX") {
    let x = handleCountry("https://www.amazon.com.mx/")
    return x
  }
})

async function handleCountry(content) {
  // key to cache response at
  let key = "geo-target: "

  // check cache for response object
  let cacheKey = key + content
  let cache = await responseCache.get(cacheKey)

  // serve cached response if there is one
  if (cache) {
    console.log("from cache at key: ", cacheKey)
    return cache
  }

  // if there is nothing cached, create a response by fetching the site, and then store the response in the cache for the future
  let app = await fetch(content)
  await responseCache.set(cacheKey, app)
  return app
}

This example uses also "ipinfo.io" to get user location information. First, we’re detecting the user's geographic location based on their IP address. We’ll fetch the information we need, and then convert it to json format so we can read it and use it. Then, let’s add location headers to our requests. This example will use the user’s country, stored in the header Fly-IP-Country, but we’ll save their city and region just for fun. Next, let's use these headers to change the behavior of our app based on the user's country. If the user’s request is coming from the United States, we’ll serve them the US version of our app. If they’re in Germany, give them the German version, if they're in China, serve them that, yada yada yada...

George

We’ll also want to check the cache here to see if there is a response stored to help speed things up. If there’s not, we’ll add it to the cache and serve them the app by fetching it from the origin.

Conclusion

With geo-targeting, app responses are specific to user location, in an effort to serve information that is most relevant to the user, thus driving conversions. Geo-targeting site content provides a relatively easy way to personalize content for users based on their whereabouts in the world. And when combined with an Edge App, shown in the examples above, you get the benefits of location-based results and the speed of a powerful CDN.