Pass data through Button on

Pass data through Button

You may want to pass data unique to your system through Button for easier end-to-end tracking when integrating Button. This guide goes over different methods for setting these values and reading them downstream.


User Level Activity Attribution

A user identifier is the identifier your internal systems use to uniquely identify a user account. Passing your logged-in user's identifier to Button's SDK allows Button to show you user information alongside orders and installs and to associate them with all downstream Merchant activity.

There are 2 places where you should register your user identifier with Button's SDK:

  1. After initializing the Button SDK in your app's open handler
  2. After authenticating a user's credentials in your login handler

You'll also want to call our logout function after wiping any session data in your app's logout handler.

Note: only call logout method on the Button SDK when the user initiates logging out of your app.

If you have your logged in user's identifier at the time of initializing the Button SDK, you can pass the it to the userId parameter:

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {

    Button.shared().configure(withApplicationId: "<#YOUR_BUTTON_APP_ID#>", userId: "<#USER_ID#>") { configError in
        if let error = configError {
            print("Error: \(error.localizedDescription)")
        }
    }

    return true
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

    [[Button sharedButton] configureWithApplicationId:"<#YOUR_BUTTON_APP_ID#>" userId: "<#USER_ID#>" completion:^(NSError *error) {
        if (error) {
          NSLog(@"Error: %@", error.localizedDescription);
        }
    }];

    return YES;
}

To register a user after authenticating a user's credentials in your login handler, use the following call:

Button.shared().setUserIdentifier("<#USER_ID#>")
[[Button sharedButton] setUserIdentifier: @"<#USER_ID#>"];

To log a user out, use the following call:

Button.shared().logOut()
[[Button sharedButton] logOut];

Associate Data with a Button or Flow

A Publisher Reference Token can be used to associate any value you'd like with any downstream Merchant activity such as orders, app-installs, etc. The value will be passed back to you in webhook requests associated with that downstream Merchant activity.

The token has a maximum length of 100 characters; if you want to store more data than that, we recommend using a value that can look up the rest of the data in your system. The token is set when fetching an app action via the publisherReference parameter.

To set the Publisher Reference Token when fetching the app action with a Button ID, use the following call:

Button.shared().fetchAppAction(withButtonId: "<#BUTTON_ID#>", context: context, publisherReference: "<#YOUR_PUBLISHER_REFERENCE#>") { appAction, error in
    if let error = configError {
        print("Error: \(error.localizedDescription)")
    }
}
[[Button sharedButton] fetchAppActionWithButtonId:@"<#BUTTON_ID#>" context:context publisherReference:"<#YOUR_PUBLISHER_REFERENCE#>" completion:^(BTNAppAction *appAction, NSError *error) {
    if (error) {
        NSLog(@"Error: %@", error.localizedDescription);
    }
}

To set the Publisher Reference Token when fetching the app action with a URL, use the following call:

Button.shared().fetchAppAction(with: "<#URL#>", publisherReference: "<#YOUR_PUBLISHER_REFERENCE#>") { appAction, error in
    if let error = configError {
        print("Error: \(error.localizedDescription)")
    }
}
[[Button sharedButton] fetchAppActionWithURL:@"<#URL#>" publisherReference:"<#YOUR_PUBLISHER_REFERENCE#>" completion:^(BTNAppAction *appAction, NSError *error) {
    if (error) {
        NSLog(@"Error: %@", error.localizedDescription);
    }
}

Receiving Identifiers in Webhooks

When you receive a webhook from Button upon completion of an order, the user identifier and Publisher Reference Token you set in the SDK will be delivered in the JSON payload in the publisher_customer_id and pub_ref values, respectively.

{
  "event_type": "tx-validated",
  "data": {
    "order_currency": "USD",
    "modified_date": "2017-01-01T20:00:00.000Z",
    "created_date": "2017-01-01T20:00:00.000Z",
    "order_line_items": [
        {
            "identifier": "sku-1234",
            "amount": 2000,
            "quantity":3,
            "description": "T-shirts",
            "attributes": {
                "size": "M"
            }
        }
    ],
    "button_id": "btn-59722058ab439774",
    "order_id": "order-1",
    "account_id": "acc-67a18cc120e5235d",
    "btn_ref": "srctok-713c963c1c30c55f",
    "currency": "USD",
    "pub_ref": "publisher-token", # Here is the Publisher Reference Token you set in the SDK!
    "status": "validated",
    "event_date": "2017-01-01T20:00:00Z",
    "order_total": 6000,
    "advertising_id": "02840796-66B3-4C96-AF72-84393B4925BF",
    "publisher_organization": "org-1418faaf0504783b",
    "commerce_organization": "org-0a94e4380a410aab",
    "button_order_id": "btnorder-4db429a36440c00e",
    "publisher_customer_id": "6815467b-93ca-47ce-97ae-bcf8b4292a87", # Here is the user ID you set in the SDK!
    "id": "tx-070dd05f5db6e4ec",
    "category": "new-user-order",
    "validated_date": "2016-06-01T19:02:09Z"
  },
  "id": "hook-7486e4aab57bb23e",
  "request_id": "attempt-5c302d097767a327"
}

Sample code

Here are sample applications in popular web frameworks that accept webhooks and read both the Publisher Reference Token and user ID:

var express = require('express');
var app = express();

var bodyParser = require('body-parser');
var crypto = require('crypto');

var port = process.env.PORT || 5000;

var WEBHOOK_SECRET = 'YOUR_WEBHOOK_SECRET'

app.use(bodyParser.json({ verify: verify, type: 'application/json' }));

app.post('/webhook', function(req, res) {
  // Here is the Publisher Reference Token you set in the SDK!
  var publisherReference = req.body.data.pub_ref;

  // Here is the user ID you set in the SDK!
  var userId =  req.body.data.publisher_customer_id;

  res.sendStatus(200);
})

app.listen(port, function() {
  console.log('Listening on port: ' + port)
})

function verify(req, res, buf, encoding) {
  if (req.headers['x-button-signature'] !== signature(buf)) {
    throw new Error('Invalid Webhook Signature');
  }
}

function signature(requestBody) {
  return crypto.createHmac('sha256', WEBHOOK_SECRET)
    .update(requestBody)
    .digest('hex');
}

require 'sinatra'

require 'openssl'
require 'json'

WEBHOOK_SECRET = 'YOUR_WEBHOOK_SECRET'

post '/webhook' do
  request_body = request.body.read
  raise 'Invalid Webhook Signature' if request.env["HTTP_X_BUTTON_SIGNATURE"] != signature(request_body)

  json = JSON.parse(request_body)

  # Here is the Publisher Reference Token you set in the SDK!
  publisher_reference = json['data']['pub_ref']

  # Here is the user ID you set in the SDK!
  user_id =  json['data']['publisher_customer_id']

  status 200
end

def signature request_body
  OpenSSL::HMAC.hexdigest(
    OpenSSL::Digest.new('sha256'),
    WEBHOOK_SECRET,
    request_body
  )
end

import os
import hmac
import hashlib

from flask import Flask, request, abort

app = Flask(__name__)

WEBHOOK_SECRET = 'YOUR_WEBHOOK_SECRET'

@app.route('/webhook', methods=['POST'])
def webhook():
    computed_signature = signature(request.data)
    sent_signature = request.headers.get('X-Button-Signature').encode('utf8')

    if not hmac.compare_digest(computed_signature, sent_signature):
        abort(403)

    # Here is the Publisher Reference Token you set in the SDK!
    publisher_reference = request.json['data']['pub_ref']

    # Here is the user ID you set in the SDK!
    user_id =  request.json['data']['publisher_customer_id']

    return 'ok', 200

def signature(request_body):
    return hmac.new(WEBHOOK_SECRET, request_body, hashlib.sha256).hexdigest()

if __name__ == "__main__":
    app.run()

The full source code for each of these sample apps can be found here.

For more information on webhooks, see this guide.