Distance Targeting

🚧

Caution

Distance Targeting, previously known as GeoDistance Targeting, requires the Business or Enterprise Plans.

Distance Targeting is a feature within Kevel that allows your product to surface relevant promotions based on customer location (or search location) relative to advertiser locations.

It unlocks 2 main use cases.

1. User-specified radius: Show promoted listings located within a certain distance of your customer’s location. In this case, the promotion location(s) are stored on the flight without a radius, and a radius is specified in the ad request.

3278

An example of user-specified radius: A rental site shows promoted vacation homes within 25 miles of the city where the customer wants to visit.

2. Advertiser-specified radius: Show promotions only when a customer is within a certain distance of your advertiser’s location. In this case, the promotion location(s) are stored on the flight along with a radius.

2834

An example of advertiser-specified radius: A food ordering platform shows takeout deals to a customer within range of restaurant locations.

👍

Information

Distance Targeting should not be confused with Geo-Targeting, which targets ads to users located within specified geopolitical regions.

How Distance Targeting Works

The basic unit of Distance Targeting is the geometry. A geometry contains the latitude and longitude of the center point and, for advertiser-specified radius, the radius. (If you use a street address to determine latitude and longitude, the street address is also saved as part of the geometry.)

Each geometry is associated with a flight, and a flight can have multiple geometries associated with it. You can create geometries via the Management API or via the flight settings page in the UI.

There is an additional Distance Targeting setting on the flight: the Require Strict Location checkbox (or the RequireStrictLocation boolean in the API). When this box is checked, the ads in the flight cannot serve unless a latitude/longitude is explicitly passed in the ad request. This is the recommended setting, as it is useful in cases where the IP address on the ad request is not precise enough to accurately determine a user's location.

👍

Information

We recommend that you pass the intended latitude and longitude explicitly in the ad request when using the Distance Targeting feature. Coordinates determine a user's location more precisely than resolving an IP address to a geolocation, since the location of an IP address is variable and can change over time.

User location for the sake of Distance Targeting is determined in the ad request using the intendedLatitude and intendedLongitude parameters. If intendedLatitude and intendedLongitude are not provided, customer location will be derived from the following, in order:

  • If user and key are present in the Decision API request, customer location will be derived from the IP address saved in the related UserDB record.
  • The IP address passed within the Decision API request in the ip parameter.
  • An IP override on the X-Forwarded-For HTTP header, if present.
  • The IP address of the user making the request.

Note that intendedLatitude and intendedLongitude are used only be used for Distance Targeting and do not affect other ad serving decisions or geo-locations in reporting. This means that an impression from the UK with an Intended Latitude and Longitude in Florida will appear in reporting as originating from the UK.

The Decision API includes an additional Distance Targeting setting: IncludeMatchedPoints, which returns a list of all geometries on the winning ad that are within targeting range of the user's location. These geometries are matched points. Matched points are especially useful for displaying multiple nearby points on a map if your use case involves displaying points on a map.

Distance Targeting Resource Limits

By default, each flight is limited to 25 geometries. If you wish to adjust these resource limits, please contact your account manager.

When flights that contain geometries are deleted, or campaigns and advertisers that contain flights with geometries are deleted, those geometries will no longer count toward your resource limit.

📘

Note

You cannot add geometries to deleted flights, or flights that belong to deleted campaigns or advertisers.

Setting Up Distance Targeting - API

For the full documentation on the Distance Targeting endpoints, refer to the API documentation.

You can POST Distance Targeting geometry objects that are associated with a flight ID via a URL parameter. The geometry objects must either use latitude and longitude or a street address.

To use user-specified radius, omit Distance, as you will specify radius in the ad request. For advertiser-specified radius, specify a Distance.

// Using latitude & longitude
{
  "Latitude": 5.2359,
  "Longitude": -14.2227
  "Distance": 52.5, // km, max 500. Omit for user-specified radius
}

// Using street address
{
  "StreetAddress": "1 Kevel Boulevard, Keveltown NC 27701",
  "Distance": 50.0 // km, max 500. Omit for user-specified radius
}

The response to your POST will contain the data from your payload, the FlightId, the Latitude and Longitude (if they needed to be resolved from the StreetAddress) and the Id of the object:

{
  "Distance": 52,
  "StreetAddress": "1 Kevel Boulevard, Keveltown NC 27701",
  "FlightId": 123456,
  "Latitude": 35.9950488,
  "Longitude": -78.9081815,
  "Id": 1234
}

You can also GET, PUT, and DELETE` geometry objects. Refer to the API documentation for more information.

The flight entity contains a read-only GeoDistanceTargeting object containing a list of all geometries associated with the flight:

"GeoDistanceTargeting": [
    {
      "Id": 1234,
      "StreetAddress": null,
      "Latitude": 88,
      "Longitude": 4.12344,
      "Distance": 2.5
    },
    {
      "Id": 1235,
      "StreetAddress": "Kevel",
      "Latitude": 36.0028,
      "Longitude": -78.90403,
      "Distance": 10
    }
  ]

The flight entity also contains the RequireStrictLocation boolean. This can be read, set, and updated on the flight. Refer to the flight endpoint API documentation for more information.

Setting Up Distance Targeting - UI

You can create Distance Targeting geometries on the flight level.

  1. Edit the flight settings page and click the "Distance Targeting" link to jump to the Distance Targeting settings.
  2. Enter a Street Address, or select "Enter a latitude & longitude" to enter coordinates instead. Street addresses are resolved to latitude and longitude, but the original address is saved with the geometry.
  3. For advertiser-specified radius, specify a Distance. For user-specified radius, leave Distance blank and specify a radius in the ad request.
  4. Click "Add" and repeat to add more geometries.
  5. (Optional) Checking the "Require Strict Location" checkbox causes the ads in the flight to only serve if Latitude and Longitude is explicitly passed in the ad request.
983

A flight set up for advertiser-specified radius

👍

Information

Geometries become active as soon as they are added to the flight - saving the flight is not necessary to enable them. However, you must save the flight to update the "Require Strict Location" checkbox.

Distance Targeting Ad Requests

We recommend that you request Distance targeted ads by supplying an Intended Latitude and Intended Longitude from the user (or for the desired location) with the request.

In the Decision API, these are the intendedLatitude (float) and intendedLongitude (float) parameters on the request:

curl -H 'Content-Type:application/json' -X POST -d '{"intendedLatitude":17.982,"intendedLongitude":-78.61,"placements":[{"divName":"Distance","networkId":1234,"siteId":123456,"adTypes":[5]}]}' https://e-1234.adzerk.net/api/v2
import AdzerkSDK

// Demo network, site, & ad type IDs; find your own via the Adzerk UI!
DecisionSDK.defaultNetworkId = 1234
DecisionSDK.defaultSiteId = 123456

let client = DecisionSDK()

var p = Placements.custom(divName: "Distance", adTypes: [5])

var reqOpts = PlacementRequest<StandardPlacement>.Options()
reqOpts.additionalOptions = [
  "intendedLatitude": 17.982,
  "intendedLongitude": -78.61
]

client.request(placements: [p], options: reqOpts) {response in
  dump(response)
}
val sdk = AdzerkSdk.Builder().networkId(1234).build()
val request = new Request.Builder()
    .addPlacement(Placement("Distance", 123456, (5)))
    .addAdditionalOption("intendedLatitude", 17.982)
    .addAdditionalOption("intendedLongitude", -78.61)
    .build()
  
 sdk.requestPlacement(request, object : AdzerkSdk.DecisionListener {
   override fun success(response: DecisionResponse?) {
   },
   override fun error(error: AdzerkSdk.Error?) {
   }
 })

For advertiser-specified radius, do not include a radius on the Decision API request. For user-specified radius, specify a radius parameter with value up to 100.0.

{
  "intendedLatitude": 17.982,
  "intendedLongitude": -78.61,
  "radius": 10.0 // in km, maximum 100. Omit for advertiser-specified radius
}

You can additionally request matched points on a Decision API request, which returns a list of all geometries on the winning ad that are within targeting range of the user's location. Set the includeMatchedPoints boolean to true:

curl -H 'Content-Type:application/json' -X POST -d '{"includeMatchedPoints":true,"intendedLatitude":1,"intendedLongitude":1,"placements":[{"divName":"MatchedPointsExample","networkId":1234,"siteId":123456,"adTypes":[5]}]}' https://e-1234.adzerk.net/api/v2

In ados.js ad code, pass floats to the ados_Latitude(); and ados_setLongitude(); functions. If using user-specified radius, also pass floats to ados_setRadius();

<script type="text/javascript">
  var protocol = document.location.protocol == "https:" ? "https" : "http";
  var z = document.createElement("script");
  z.type = "text/javascript";
  z.src = protocol + "://static.adzerk.net/ados.js";
  z.async = true;
  var s = document.getElementsByTagName("script")[0];
  s.parentNode.insertBefore(z,s);
</script>
<script type="text/javascript">
  var ados = ados || {};
  ados.run = ados.run || [];
  ados.run.push(function() {
    /* load placement for account: Example,
                          site: Pure Awesome,
                          size: 300x250 - Medium Rectangle */
    ados_setLatitude(17.982);
    ados_setLongitude(-78.61);
    ados_setRadius(20);
    ados_add_placement(1234, 123456, "Distance", 5);
    ados_load();
  });
</script>

<div id="Distance"></div>

If intendedLatitude and intendedLongitude are not provided, customer location will be derived from the following, in order:

  • If user and key are present in the Decision API request, customer location will be derived from the IP address saved in the related UserDB record.
  • The IP address passed within the Decision API request in the ip parameter.
  • An IP override on the X-Forwarded-For HTTP header, if present.
  • The IP address of the user making the request.
    Using IP addresses for Distance Targeting isn't recommended, since IP addresses must be geocoded to coordinates, and this resolution is less precise than supplying coordinates directly.

🚧

Caution

If you plan to read an IP address from a user's UserDB record, you must set "enableUserDBIP":true on the Decision API request.

Distance Targeting Ad Responses

Distance targeted responses are the same as other ad responses unless you request matched points on the Decision API. These will be returned as an array of objects per placement at decisions.divName.matchedPoints:

{
  "user": {
    "key": "ue1-29d8d03..."
  },
  "decisions": {
    "MatchedPointsExample": {
      "adId": 123456,
      "creativeId": 123456,
      "flightId": 123456,
      "campaignId": 12345,
      "clickUrl": "http://e-1234.adzerk.net/r?e=eyJhdiI6ND...H0&s=kh6NYxbR-61X6gyYunaB5fW04GA",
      "impressionUrl": "http://e-1234.adzerk.net/i.gif?e=eyJhdiI6ND...B9&s=vgx3m2tmbnSmmgBglFLDLBlTXGs",
      "contents": [
        {
          "type": "raw",
          "data": {
            "height": 250,
            "width": 300
          },
          "body": "Intended Location Ad",
          "customTemplate": "Intended Location Ad"
        }
      ],
      "height": 250,
      "width": 300,
      "events": [],
      "matchedPoints": [
        {
          "lat": 1,
          "lon": 1
        },
        {
          "lat":1,
          "lon":1.5
        },
        {
          "lat":1.5,
          "lon":2
        }
      ]
    }
  }
}

Note that matchedPoints will be returned from nearest to furthest.

If selection data shipping is enabled for your account, you will also see matched points in selection logs as the array of objects GeoMatchedPoints.