How to use beacon signing keys

A beacon signing workflow allows customers to request and cache ad responses from the JSON Ad API, and then distribute ad response as many times as needed by generating signed (unique) beacon URLs. You can create keys and sign beacons with the beacon signing keys you create in your settings to track the stats of cached ads.

This article outlines how beacon signing keys work. For information on the endpoint entries themselves, read our API documentation.

This feature is not enabled by default / is a beta feature. Contact support if you want this feature enabled in your account.

Adding a beacon signing key

You may add beacon siging keys to your account through your settings.

From your AdButler Dashboard,

  1. Click on Settings in the left vertical menu
  2. Under Developers & Integrations, click on the Beacon Signing section link.
  3. In the Beacon Signing Keys section, click on Add Signing Key in the top-right of the page to add your key.
    • You will need the Key ID and the Signing Key values after saving.

Validating a signed url

To test signed URLs, you may use the Signing Validation tool found in the Beacon Signing Keys settings.

Click on the Signing Validation button in the top-right which is found beside the "Add Signing Key" button.

Ad request flow with beacon signing

  1. A customer requests an ad from the JSON Ad API using an additional flag deferred_signing=1.
  2. Before the ad is returned to the end user, the customer signs each beacon:
    • Appends the signing key id to the beacon URL
    • Appends the current microtime to the beacon URL
    • Generates a hash using the shared key and the modified beacon URL
    • Appends the signing hash to the beacon URL
  3. The user's browser, app, etc. sends beacons, and the stats are updated accordingly.

Requesting unsigned ads

When requesting ads via API, you can include the defer_signing parameter. This returns the viewability, click, and accupixel beacons without a generated hash or timestamp. These unsigned URLs are considered invalid until properly signed.

JSON Ad API GET

When making GET requests, you may append ;defer_signing=1 to the zone request URL.

https://servedbyadbutler.com/adserve/;ID=123456;size=300x250;setID=123456;type=json;defer_signing=1

JSON Ad API POST

When making a POST request, the defer_signing field should be included in the data value as a JSON key-value pair.

curl --location 'https://servedbyadbutler.com/adserve' \
--header 'Content-Type: application/json' \
-H 'Accept-Encoding: gzip' \
-d '{
    "ID": 123456,
    "setID": 123456,
    "type": "json",
    "defer_signing": 1
}'

Signable response fields

The relevant beacon URLs in JSON responses are as follows:

  • redirect_url
  • accupixel_url
  • viewable_url
  • eligible_url

For example, an unsigned eligible beacon might look like this:

https://servedbyadbutler.com/adserve/;MID=123456;type=e57e9bfc3;placementID=123456;setID=123456;channelID=0;CID=123456;BID=123456;TAID=0;place=0;psrtype=api;referrer=

Beacon signing parameters

  • hc_id - The identifier of the beacon signing key.
  • mt - The timestamp in microseconds (to 6 significant digits).
  • hc - The hash of the URL prior to this token salted with the key.

A signed beacon URL would then include these paramters generated programmatically in your implementation.

Example (shortened for readability):

https://servedbyadbutler.com/adserve/(...);hc_id=SIGNING_KEY_ID;mt=MICROTIME;hc=SIGNING_HASH

IMPORTANT NOTE

  • When signing viewability or accupixel beacons, your URL delimiter will be a ;.
  • When signing click beacons, your URL delimiter will be a &.

Example signing implementations

While these sample implementations should work as-is, they may require some adjustment for your environment.

Generic example

function getMicrotimeAsInt() {
    ...
}

function signUrl(unsignedUrl, signingKeyId, signingKey, delimiter) {
    // Get the current microtime as an integer (no floats)
    var currentMicrotimeAsInt = getMicrotimeAsInt();

    // Append the signing key id, and the microtime value
    unsignedUrl += delimiter + "hc_id=" + signingKeyId;
    unsignedUrl += delimiter + "mt=" + currentMicrotimeAsInt;

    // Sign the URL by hashing the unsigned url and the signing key
    var hash = sha1( unsignedUrl + signingKey );

    // Append the hash to to the unsigned URL
    var signedUrl = unsignedUrl + delimiter + "hc=" + hash;

    return signedUrl;
}

JavaScript

If you are using Node.js, you would need the Crypto-JS module or equivalent.

npm install crypto-js

Sample code:

const CryptoJS = require('crypto-js');

// Function to get microtime
function getMicrotimeAsInt() {
  return (new Date().getTime() * 1e6).toString();
}

// Function to generate signed URL
function generateSignedURL(url, signingKeyId, signingKey, delimiter) {
  // Get microtime
  const microtime = getMicrotimeAsInt();

  // Append the signing key id and microtime
  const unsignedUrl = `${url}${delimiter}hc_id=${signingKeyId}${delimiter}mt=${microtime}`;

  // Generate SHA1 hash of the unsigned url + signing key
  const hash = CryptoJS.SHA1(unsignedUrl + signingKey).toString();

  // Append signing key id, microtime and hash to the URL
  const signedURL = `${unsignedUrl}${delimiter}hc=${hash}`;

  return signedURL;
}

// Sample URL and signing key
const beaconUrl = 'https://servedbyadbutler.com/adserve/...';
const signingKeyId = 'YOUR_SIGNING_KEY_ID_HERE';
const signingKey = 'YOUR_SIGNING_KEY_HERE';
const delimiter = ';'; // for click redirects this would be '&' instead

// Generate the signed URL
const signedURL = generateSignedURL(beaconUrl, signingKeyId, signingKey, delimiter);
console.log(signedURL);

PHP

<?php

// Function to get microtime
function getMicrotimeAsInt() {
    list($usec, $sec) = explode(" ", microtime());
    return intval($usec * 1e6) + intval($sec * 1e6);
}

// Function to generate signed URL
function generateSignedURL($url, $signingKeyId, $signingKey, $delimiter) {
    // Get microtime
    $microtime = getMicrotimeAsInt();

    // Append the signing key id and microtime
    $unsignedUrl = "{$url}{$delimiter}hc_id={$signingKeyId}{$delimiter}mt={$microtime}";

    // Generate SHA1 hash of the unsigned url + signing key
    $hash = sha1($unsignedUrl . $signingKey);

    // Append microtime and hash to the URL
    $signedURL = "{$unsignedUrl}{$delimiter}hc={$hash}";

    return $signedURL;
}

// Sample URL and signing key
$beaconUrl = 'https://servedbyadbutler.com/adserve/...';
$signingKey = 'YOUR_SIGNING_KEY_HERE';
$signingKeyId = 'YOUR_SIGNING_KEY_ID_HERE';
$delimiter = ';'; // for click redirects this would be '&' instead

// Generate the signed URL
$signedURL = generateSignedURL($beaconUrl, $signingKeyId, $signingKey, $delimiter);
echo $signedURL;

Tips

  • When requesting ads via API, you can include the defer_signing parameter. This returns the viewability, click, and pixel beacons without a generated hash or timestamp. These unsigned URLs are considered invalid until properly signed.

  • When signing the resulting URLs, everything before the &hc= / ;hc= token is hashed (excluding the location parameter for click beacons).

  • Make sure that when signing clicks you are using the & delimiter, and other beacons the ; delimiter.

  • You can test your signed URLs using the testing tool found in the Beacon Signing Key section of your AdButler Dashboard settings.

  • As of this writing, SHA1 is the only supported algorithm.


Can't find what you're looking for?

Send us an email

hello@adbutler.com

Visit the blog

For more ad serving tips, industry news and AdButler insights.