NAV
php javascript

Introduction

With Remarkety, you can trigger automations based on various events which occur in your system.

What are events?

Events simply describe something that happened on your website or business. Events always have a type, a time and a subject.

Some examples of events are:

You get the picture ;)

How are events used in Remarkety?

Events are used within Remarkety to:

Sending Events

Event Format

All events must have a type. Remarkety has some built-in event types for e-commerce which you should use if you are sending e-commerce related events. In addition, you can send us any other type of custom event, but we will not be able to perform advanced e-commerce related analytics on them.

The built-in event types are specified in the E-Commerce Event Types section. For sending your own custom events, please see the Custom Events section.

Server-Side API

<?php

$storeId = "AAABBB";            // Unique per remarkety account
$apiKey = "SuperSecretApiKey";  // Get this from Remarkety 
$eventType = "customers/update"; // See "Event types"
$domain = "kingslanding.com";   // Your store's domain
$platform = "MAGENTO";          // Per-platform setting

$headers = [
    "x-domain: $domain",
    "x-platform: $platform",
    "x-token: $apiKey",
    "x-event-type: $eventType",
    'Content-Type: application/json; charset=UTF-8'
];

$customerData = [
    'created_at' => '2017-04-04T15:12:21-05:00',
    'email' => 'john.snow@thewall.org',
    'first_name' => 'John',
    'last_name' => 'Snow',
    'updated_at' => '2017-04-04T15:12:21-05:00',
    'accepts_marketing' => true
];

$dataString = json_encode($customerData);

$ch = curl_init("https://webhooks.remarkety.com/webhooks/?storeId=$storeId");
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch, CURLOPT_POSTFIELDS, $dataString);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

$result = curl_exec($ch);
var storeId = "AAABBB";             // Unique per remarkety account - get yours from the API setting page
var eventType = "customers/update"; // See "Event types"

var data = JSON.stringify({
  "email": "john.snow@thewall.org",
  "first_name": "John",
  "last_name": "Snow",
  "accepts_marketing": true
});

// If run server-side, send the request directly to our webhook endpoint, and include your API token
var token ="<Your API token>";  // Never expose this client-side!
var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === 4) {
    console.log(this.responseText);
  }
});

xhr.open("POST", "https://webhooks.remarkety.com/webhooks/store/"+storeId);
xhr.setRequestHeader("Content-Type", "application/json");
xhr.setRequestHeader("x-event-type", eventType);
xhr.setRequestHeader("x-token", token);
xhr.setRequestHeader("Cache-Control", "no-cache");

xhr.send(data);

The request must be a POST request to our endpoint. The request needs to include the following headers:

Header          Value Example
Content-Type application/json; charset=UTF-8
x-event-type The event type customers/update
x-api-key Your Remarkety API Key (not necessary on client-side events) abc123
x-domain Your domain (optional) my.store.com
x-platform Your e-commerce platform (optional). For custom events use "custom". MAGENTO1
x-event-time UNIX timestamp.
When this event occurred. By default, Remarkety assumes events happen when a request is made. Add this header if you'd like to track an event that happened in past.
1573649331

The body of the request is simply the event JSON itself.

Client-Side API

Remarkety's client-side library allows you to send events to Remarkety based on the visitor's actions on the store.

You can also send eCommerce events using the client-side library based on the event payload described on the E-Commerce event types docs.

Adding the client-side snippet

For client-side library examples switch to "javascript" examples
<script>
var _rmData = _rmData || [];
_rmData.push(['setStoreKey', '<STORE_ID>']);
</script>
<script>(function(d, t) {
var g = d.createElement(t),
s = d.getElementsByTagName(t)[0];
g.src = 'https://d3ryumxhbd2uw7.cloudfront.net/webtracking/track.js';
s.parentNode.insertBefore(g, s);
}(document, 'script'));
</script>

All pages on the website should include this piece of code, just before the </body> tag.

Make sure to include the correct <STORE_ID> which you can find under Settings > API Keys in your account.








Identifying Visitors

For client-side library examples switch to "javascript" examples
var _rmData = _rmData || [];
//Identify using email address
_rmData.push(['setCustomer', '<CUSTOMER_EMAIL>']);

//Identify using customer id
_rmData.push(['setCustomerId', '<CUSTOMER_ID>']);

//Identify the customer and update the accepts_marketing and first_name properties
_rmData.push(['setCustomer', {
    "email": "john.snow@thewall.org",
    "first_name": "John",
    "accepts_marketing": true
}]);

The setCustomer and setCustomerId method allows you identify the visitors based on their email address or your internal customer id.

You can also use the setCustomer method with customer information, that will get updated in Remarkety contact's details.

For the full list of customer properties please check the "customers/create" properties.

Please Note:





Sending events

For client-side library examples switch to "javascript" examples
var _rmData = _rmData || [];
//Sending an eCommerce event for updating the customer data
var eventType = 'customers/update';
var data = {
             "email": "john.snow@thewall.org",
             "first_name": "John",
             "last_name": "Snow",
             "accepts_marketing": true
           };
_rmData.push(['track', eventType, data]);

//Sending a custom event based on visitor's action on the website
var eventType = 'site-search';
var data = {
             "searchKeyword": "Red shorts",
             "result_1_title": "Swim Short",
             "result_1_image": "http://www.example.com/swim_shorts.png"
           };
_rmData.push(['track', eventType, data]);

When sending events you can choose to send eCommerce-related events or you can choose to send any custom event with custom properties.

















Product view events

For client-side library examples switch to "javascript" examples
//Example code for productView event
var _rmData = _rmData || [];
_rmData.push(['productView', {
   productId: '1112222',
   productCategories: ['Men / Shorts', 'Men / Swimwear']
}]);

To let Remarkety know that a visitor viewed a particular product, for using in the "Browse Abandonment" automation or product recommendations, you should send the productView event with the properties listed below.

These properties should match the product id as received from the products feed.

Property name description required
productId The product id that the visitor viewed. Yes
productCategories List of categories that this product attached to. No

E-Commerce Event Types

Following is a list of e-commerce Event Types and their JSON format. Each event type has several mandatory fields, which must by included in the JSON. The rest are optional, but the more data you send the more accurate Remarkety can be in analyzing the data and communicating with your customer.

The event type must be specified in the x-event-type header.

customers/create

{
  "accepts_marketing": true,
  "birthdate": "1997-02-26",
  "created_at": "2012-02-15T15:12:21-05:00",
  "default_address": {
    "country_code": "USA",
    "region": "MO",
    "zip": "45415-3423",
    "city": "Kansas City",
    "street": "4647 Sunset Drive",
    "phone": "1-923-555-5555"
  },
  "email": "guy@remarkety.com",
  "first_name": "Guy",
  "last_name": "Harel",
  "gender": "M",
  "groups": [
    {
      "id": 1,
      "name": "VIP Customers"
    }
  ],
  "id": 1234,
  "rewards": {
    "points": 10
  },
  "tags": [
    "tag1",
    "tag2"
  ],
  "updated_at": "2012-02-15T15:12:21-05:00"
}

Used to inform Remarkety about customers being created or updated.

Mandatory Fields

Field Data type Description
email string Email must be valid

Optional Fields

Field Data type Description Default Value
accepts_marketing Boolean If the user did not explicitly opt in or out on the website, send null here. Check your account settings to determine whether unknown value allows sending emails to the customers by default or not null (Unknown)
created_at Date The registration date of the customer to your website. Current time
tags Array of Strings []
append_tags boolean If the contact already exists in Remarkety, pass true to append new tags instead of replacing existing tags false
gender M/F

customers/update

Same format as customers/create. Used to inform Remarkety about a customer update.

If the customer has changed her email address, make sure to send a valid id. Remarkety will then update the customer record based on this id. Otherwise, a new customer might be created with the new email.

orders/create

{
  "created_at": "2012-02-15T15:12:21-05:00",
  "currency": "USD",
  "customer": {
    "accepts_marketing": true,
    "birthdate": "1997-02-26",
    "created_at": "2012-02-15T15:12:21-05:00",
    "default_address": {
      "country": "United States",
      "country_code": "USA",
      "province_code": "MO",
      "zip": "45415-3423",
      "phone": "1-923-555-5555"
    },
    "email": "guy@remarkety.com",
    "first_name": "Guy",
    "gender": "M",
    "groups": [
      {
        "id": 1,
        "name": "VIP Customers"
      }
    ],
    "id": 1234,
    "info": {},
    "last_name": "Harel",
    "updated_at": "2012-02-15T15:12:21-05:00",
    "tags": "tag1,tag2",
    "title": "Mr.",
    "verified_email": true
  },
  "discount_codes": [
    {
      "code": "10OFF",
      "amount": 20,
      "type": "fixed_amount"
    }
  ],
  "email": "guy@remarkety.com",
  "fulfillment_status": "string",
  "id": 1234,
  "line_items": [
    {
      "product_id": 1234,
      "quantity": 1,
      "sku": "SKU1234",
      "name": "Blue Shirt, Size S",
      "url": "https://my.cool.store/catalog/cool-gadget.html",
      "image": "https://my.cool.store/images/cool-gadget.jpg",
      "title": "Shirt",
      "variant_title": "Blue",
      "vendor": "Castro",
      "price": 100,
      "taxable": true,
      "tax_lines": [
        {
          "title": "VAT",
          "price": 18,
          "rate": 0.18
        }
      ],
      "added_at": "2012-02-15T15:12:21-05:00",
    }
  ],
  "note": "Please don't break this!",
  "shipping_lines": [
    {
      "title": "Fedex 2-day",
      "price": 20,
      "code": "fedex-2-day"
    }
  ],
  "status": {
    "code": "S",
    "name": "Shipped"
  },
  "financial_status": {
    "code": "S",
    "name": "Shipped"
  },
  "subtotal_price": 100,
  "tax_lines": [
    {
      "title": "VAT",
      "price": 18,
      "rate": 0.18
    }
  ],
  "taxes_included": true,
  "test": true,
  "total_discounts": 20,
  "total_line_items_price": 100,
  "total_price": 100,
  "total_shipping": 20,
  "total_tax": 18,
  "total_weight": 150,
  "updated_at": "2012-02-15T15:12:21-05:00",
  "channel": "POS"
}

Used to inform Remarkety about a new order in the system. Send us much information as possible here.

Note that the order information is a nested object which also includes information about the customer and lineitems.

Mandatory fields

Field Data type Description
id String The order id in your backoffice
created_at Datetime string (with timezone) Order creation date.
customer.accepts_marketing Boolean Is the customer opted in to marketing emails
customer.created_at Datetime string (with timezone) The time this customer was created
customer.updated_at Datetime string (with timezone) The time this customer was last updated
customer.email Valid email The email associated with the customer.
lineitems[].product_id String Your backoffice's product id
lineitems[].quantity Numeric The amount of this item in the order
lineitems[].sku String The SKU of this item
lineitems[].name String The name of the product to be displayed to the user
lineitems[].url URL A link to this item's product page in your store
lineitems[].image URL URL of the image of this item or product
lineitems[].price Numeric The price of this item in this specific order
status.name String The name of the order status
subtotal_price Numeric Order subtotal
total_discounts Numeric The total of all discounts applied. This should be a positive number.
total_shipping Numeric Shipping costs for this order
total_tax Numeric Tax added to this order
total_price Numeric The total that the customer was charged for this order

orders/update

Same format as orders/create. Inform Remarkety about an order being updated (status changed, products changed, etc)

products/create

{
  "body_html": "This is an <strong>awesome</strong> product!",
  "categories": [
    {
      "code": 12,
      "name": "Men's clothing"
    }
  ],
  "created_at": "2012-02-15T15:12:21-05:00",
  "id": 1234,
  "image": {
    "id": 1111,
    "product_id": 1234,
    "created_at": "2012-02-15T15:12:21-05:00",
    "updated_at": "2012-02-15T15:12:21-05:00",
    "src": "https://my.cool.store/image1.jpg",
    "variant_ids": [
      null
    ]
  },
  "images": [
    {
      "id": 1111,
      "product_id": 1234,
      "created_at": "2012-02-15T15:12:21-05:00",
      "updated_at": "2012-02-15T15:12:21-05:00",
      "src": "https://my.cool.store/image1.jpg",
      "variant_ids": [
        null
      ]
    }
  ],
  "options": [
    {
      "id": 4444,
      "name": "Color",
      "values": [
        "red"
      ]
    }
  ],
  "published_at": "2012-02-15T15:12:21-05:00",
  "product_exists": true,
  "sku": "SKU1234",
  "tags": "cool,new",
  "title": "Cool Gadget",
  "updated_at": "2012-02-15T15:12:21-05:00",
  "url": "https://my.cool.store/catalog/cool-gadget.html",
  "variants": [
    {
      "barcode": "string",
      "currency": "USD",
      "created_at": "2012-02-15T15:12:21-05:00",
      "fulfillment_service": "string",
      "id": 12345,
      "image": "https://my.cool.store/images/image1.jpg",
      "inventory_quantity": 12,
      "price": 199.23,
      "product_id": 1234,
      "sku": "SKU1234",
      "taxable": true,
      "title": "Blue Shirt",
      "option1": "Blue",
      "updated_at": "2012-02-15T15:12:21-05:00",
      "requires_shipping": true,
      "weight": 150,
      "weight_unit": "g"
    }
  ],
  "vendor": "Samsung"
}

Inform Remarkety about a new product.

What are product variants?

A variant is a "subtype" of a more generic product. For example, for the product "Nike Air Jordan", you would have different variants such as White / Size 12 or Black / Size 12.

For an iPhone 7, you might have the Silver / 32GB and the Gold / 256GB variants.

If you don't have such variants (for example: you sell A Chair), then the product would have exactly one variant, with most of the properties (SKU, id, etc) being duplicated into the variant.

Mandatory fields

Field Data type Description
id String The product id in your backoffice
sku String The product SKU
created_at Datetime string (with timezone) The time this product was created
image.src URL URL of the main product image thumbnail
product_exists Boolean Is this product currently for sale in the store?
title String Short title describing the product
url URL Link to the product page on the store website
vendor String Name of the product vendor/manufacturer
variants[].id String The backoffice ID of this specific variant
variants[].image URL The image URL of this variant
variants[].inventory_quantity Numeric # of items youhave in stock
variants[].product_id Numeric The id of this variant's parent
variants[].sku String The SKU of this product variant
variants[].title String The title of this specific variant

products/update

Similar to products/create, inform Remarkety about a product that's been updated.

products/delete

Products cannot be deleted, but they can be updated so that they are no longer available for recommendations. To do this, update the product with product_exists=false.

carts/create

{
    "abandoned_checkout_url": "https://my.cool.store/carts/2341234sdfasdf",
    "billing_address": {
      "country": "United States",
      "country_code": "USA",
      "province_code": "MO",
      "zip": "45415-3423",
      "phone": "1-923-555-5555"
    },
    "accepts_marketing": true,
    "cart_token": "cart_abc",
    "created_at": "2012-02-15T15:12:21-05:00",
    "currency": "USD",
    "customer": {
      "accepts_marketing": true,
      "birthdate": "1997-02-26",
      "created_at": "2012-02-15T15:12:21-05:00",
      "default_address": {
        "country": "United States",
        "country_code": "USA",
        "province_code": "MO",
        "zip": "45415-3423",
        "phone": "1-923-555-5555"
      },
      "email": "guy@remarkety.com",
      "first_name": "Guy",
      "gender": "M",
      "groups": [
        {
          "id": 1,
          "name": "VIP Customers"
        }
      ],
      "id": 1234,
      "info": {},
      "last_name": "Harel",
      "updated_at": "2012-02-15T15:12:21-05:00",
      "tags": "tag1,tag2",
      "title": "Mr.",
      "verified_email": true
    },
    "discount_codes": [
      {
        "code": "10OFF",
        "amount": 20,
        "type": "fixed_amount"
      }
    ],
    "email": "guy@remarkety.com",
    "fulfillment_status": "string",
    "id": 1234,
    "line_items": [
      {
        "product_id": 1234,
        "quantity": 1,
        "sku": "SKU1234",
        "name": "Blue Shirt, Size S",
        "title": "Shirt",
        "variant_title": "Blue",
        "vendor": "Castro",
        "price": 100,
        "taxable": true,
        "tax_lines": [
          {
            "title": "VAT",
            "price": 18,
            "rate": 0.18
          }
        ],
        "added_at": "2012-02-15T15:12:21-05:00"
      }
    ],
    "note": "Please don't break this!",
    "shipping_address": {
      "country": "United States",
      "country_code": "USA",
      "province_code": "MO",
      "zip": "45415-3423",
      "phone": "1-923-555-5555"
    },
    "shipping_lines": [
      {
        "title": "Fedex 2-day",
        "price": 20,
        "code": "fedex-2-day"
      }
    ],
    "subtotal_price": 100,
    "tax_lines": [
      {
        "title": "VAT",
        "price": 18,
        "rate": 0.18
      }
    ],
    "taxes_included": true,
    "total_discounts": 20,
    "total_line_items_price": 100,
    "total_price": 100,
    "total_shipping": 20,
    "total_tax": 18,
    "total_weight": 150,
    "updated_at": "2012-02-15T15:12:21-05:00"
  }

When a user browses the site, they will start (hopefully) adding products to the cart. As long as the cart did not turn into an actual order, you should use the carts endpoints in order to let Remarkety know about them. If the cart is anonymous (most are...), the customer and emails fields can be sent as null.

Mandatory fields

Field Data type Description
abandoned_checkout_url URL This URL should lead to the cart contents. Optimally, this URL should work on any browser.
accepts_marketing Boolean Does this customer accept email marketing?
created_at Datetime string (with timezone) Time that this cart was originally created
currency String 3-letter code of this cart's currency
customer Boolean If this cart is not a guest (anonymouns) cart, send the customer information here. Otherwise set to null
customer.accepts_marketing Boolean Does this customer accept marketing?
customer.email Email The email address of this customer
customer.id String The backoffice customer id
email String For guest checkouts, this can be set even if there is no registered customer. If unknown, set as null
id String The cart ID in the backoffice. Used when updating (and deleting) the cart.
title String Short title describing the product
line_items Array The products in the cart. Same as in the order
total_discounts Numeric Discounts given for this cart
total_price Numeric Total price of this cart, incl tax, discounts and shipping
updated_at Datetime (with timezone) Last time this cart was updated. Very important for timing the emails.

carts/update

Same format as carts/create. Make sure to keep the same id so that carts don't get duplicated.

newsletter/subscribe

{
  "email": "shopper@gmail.com",
  "first_name": "Edgar",
  "last_name": "Poe",
  "sms_phone_number_e164": "+12025550137",
  "customerId": "111112",
  "tags": ["politics", "sport"],
  "double_optin_required": false
}
var storeId = "AAABBB";             // Unique per remarkety account - get yours from the API setting page
var eventType = "newsletter/subscribe"; // See "Event types"

var data = JSON.stringify({
    "email": "shopper@gmail.com",
    "first_name": "Edgar",
    "last_name": "Poe",
    "sms_phone_number_e164": "+12025550137",
    "customerId": "111112",
    "tags": ["politics", "sport"]
});

// If run client-side, use our tracking script:
var _rmData = _rmData || [];
_rmData.push(['setStoreKey', storeId]); // Only needs to be run once on the page
_rmData.push(['track', eventType, data]);
// End client-side code

Send this event to inform Remarkety of a customer's explicit wish to receive email newsletters or SMS blasts. When Remarkety received this event, we will send an opt-in confirmation based on the account settings and the double_optin_required field.

Make sure you send the sms_phone_number_e164 field as an E.164 formatted phone number.

newsletter/unsubscribe

{
"email": "shopper@gmail.com"
}
var storeId = "AAABBB";             // Unique per remarkety account - get yours from the API setting page
var eventType = "newsletter/unsubscribe"; // See "Event types"

var data = JSON.stringify({
    "email": "shopper@gmail.com"
});

// If run client-side, use our tracking script:
var _rmData = _rmData || [];
_rmData.push(['setStoreKey', storeId]); // Only needs to be run once on the page
_rmData.push(['track', eventType, data]);
// End client-side code

Inform Remarkety that a shopper wishes to unsubscribe. We will add this email to our suppression list, so that if the customer record is updated from different sources, we will not send marketing materials to this user, even if the customer record contains accepts_marketing: true.

If you would like to resubscribe the customer after an unsusbcribe event, send an explicit newsletter/subscribe event.

Custom Events

For client-side library examples switch to "javascript" examples

// Send a site-search event

var _rmData = _rmData || [];

//Identify using email address
var customerEmail = "<Your customer email here>";
_rmData.push(['setCustomerEmail', customerEmail]);

var eventType = 'site-search';
var data = {
             "searchKeyword": "Red shorts",
             "result_1_title": "Swim Short",
             "result_1_image": "http://www.example.com/swim_shorts.png"
           };
_rmData.push(['track', eventType, data]); 


// On a different page - send a room booking event

var _rmData = _rmData || [];

var customerEmail = "<Your customer email here>";
_rmData.push(['setCustomerEmail', customerEmail]);

var eventType = 'room-booked';
var data = {
             "lodging": {
                 "name": "Kempinski Seychelles Resort",
                 "stars": 5,
                 "type": "resort",
                 "image": "https://r-ec.bstatic.com/images/hotel/max1024x768/169/16951276.jpg"
             },
             "guest": {
                "reservation_name": "John and Jane Doe"   
             }
           };
_rmData.push(['track', eventType, data]); 

In addition to the built-in eCommerce events, you can use our client-side tracking script to send custom events as well. These events, with their associated properties, can be used to trigger automations inside Remarkety.

Top-level properties can be used to filter the events triggering the automation. Any and all properties sent in the event can be used inside the email template triggered by this event.

See some usage examples on the right.

Please note: When sending any client-side event (including custom events), the user must first be identified. We currently don't track events that were sent without a user being identified first. Please read here on how to identify users.

Receiving Events

In many cases, in addition to sending events to Remarkety, you'd also like to be informed on actions that Remarkety performs or knows about, such as email sends, opens, clicks and unsubscribes.

Remarkety supports publishing these events via JSON webhooks. You supply an SSL (https) endpoint, and we will POST events to that endpoint as detailed below.

Setup

Setup your receiving endpoint in your Remarkety Settings page.

Webhook Structure

POST /endpoint.yoursite.com HTTP/1.1
X-Event-Hmac-SHA256: 4293d6f6232a9d346fbd5da0ba0c9a86851675507b750509373f227414f3cb98
X-Event-Topic: newsletter/subscribed
Content-Type: application/json
User-Agent: Remarkety
Cache-Control: no-cache

{
    "email": "john@doe.com",
    "ip_signup": "10.0.0.1",
    "ip_opt": "10.0.0.1",
    "properties": {
        "first_name": "John",
        "last_name": "Doe",
        "campaign": "Lead gen #3"
    }
}

Our POST to your endpoint will have the structure shown on the right:

Headers

Header Purpose
X-Event-Hmac-SHA256 Message digest for authentication - see below
X-Event-Topic The event topic, or type

Body

The request body will contain JSON-formatted text as detailed in the topics below.

Authentication

<?php
define('SHARED_SECRET', '<shared secret>');

function verify_webhook($data, $hmac_header)
{
  $calculated_hmac = base64_encode(hash_hmac('sha256', $data, SHARED_SECRET, true));
  return hash_equals($hmac_header, $calculated_hmac);
}


$hmac_header = $_SERVER['HTTP_X_EVENT_HMAC_SHA256'];
$data = file_get_contents('php://input');
$verified = verify_webhook($data, $hmac_header);
if ($verified) {
    $payload = json_decode($data);
    $eventTopic = $_SERVER['HTTP_X_EVENT_TOPIC'];
} else {
    error_log("Invalid signature");
}

In order to verify that the request came from Remarkety, you can use the X-Event-Hmac-SHA256 header, which includes a digital signature of the message contents (body only - not including the headers). We create the signature using the Shared Secret provided in the app. On the right is a PHP example on how to verify the signature.

Retries and Errors

We expect your endpoint to respond within 5 seconds with a 2xx return code. In case the request exceeds the timeout or returns with a 5xx error code, we will continue retrying in increasing intervals, for 2 hours. If we fail after 2 hours, we will stop retrying and will send an email to the account administrator.

Event Topics and Payloads

Common fields:

Field Purpose
timestamp The timestamp of the event itself
email The recipient's email address (cc or bcc will not trigger events)
campaign_name The plain-text name of the campaign that triggered this email
campaign_group The plain-text name of the campaign group
campaign_id The internal Remarkety id of the campaign
umk A unique identifier per email message
useragent The useragent header as sent by the recipient's email client
ip The ip address of the recipient

email/sent

{
  "timestamp": "2018-04-12T12:50:00+00:00",
  "email": "john@doe.com",
  "campaign_name": "Abandoned cart #1",
  "campaign_id": 13118,
  "umk": "5acf31d0b22410.937575625acf31d0b"
}

Sent when an email is sent to the recipient.

email/clicked

{
  "timestamp": "2018-04-12T12:50:00+00:00",
  "email": "john@doe.com",
  "campaign_name": "Abandoned cart #1",
  "campaign_id": 13118,
  "umk": "5acf31d0b22410.937575625acf31d0b",
  "link_url": "https://my.website.com/some-page",
  "useragent": "Mozilla/5.0 (Windows NT 5.1; rv:11.0) Gecko Firefox/11.0 (via ggpht.com GoogleImageProxy)",
  "ip": "1.2.3.4"
}

Sent when a recipient clicks on a link inside an email

email/opened

{
  "timestamp": "2018-04-12T12:50:00+00:00",
  "email": "john@doe.com",
  "campaign_name": "Abandoned cart #1",
  "campaign_id": 13118,
  "umk": "5acf31d0b22410.937575625acf31d0b",
  "useragent": "Mozilla/5.0 (Windows NT 5.1; rv:11.0) Gecko Firefox/11.0 (via ggpht.com GoogleImageProxy)",
  "ip": "1.2.3.4"
}

Sent when an email is opened. This is not 100% correct because open tracking is done via images, which are sometimes blocked and sometimes opened by the receiving mail server and not the actual, human recipient.

email/delivered

{
  "timestamp": "2018-04-12T12:50:00+00:00",
  "email": "john@doe.com",
  "campaign_name": "Abandoned cart #1",
  "campaign_id": 13118,
  "umk": "5acf31d0b22410.937575625acf31d0b"
}

Sent when the recipient's email server acknowledges receipt of the message. This does not necessarily mean that the email reached the inbox.

email/bounced

{
  "timestamp": "2018-04-12T12:50:00+00:00",
  "email": "john@doe.com",
  "campaign_name": "Abandoned cart #1",
  "campaign_id": 13118,
  "umk": "5acf31d0b22410.937575625acf31d0b",
  "reason": "554 5.4.14 Hop count exceeded - possible mail loop ATTR34 [SN1NAM04FT063.eop-NAM04.prod.protection.outlook.com]",
  "soft_bounce": true
}

Sent when the receiving email server does not accept the message. May signal a soft bounce (for example: mailbox full) or a hard bounce (address doesn't exist).

email/spam

{
  "timestamp": "2018-04-12T12:50:00+00:00",
  "email": "john@doe.com",
  "campaign_name": "Abandoned cart #1",
  "campaign_id": 13118,
  "umk": "5acf31d0b22410.937575625acf31d0b"
}

Sent when an email is marked as spam. Not all email servers send back a spam notification, gmail in particular does not.

email/unsubscribed

{
  "timestamp": "2018-04-12T12:50:00+00:00",
  "email": "john@doe.com",
  "campaign_name": "Abandoned cart #1",
  "campaign_id": 13118,
  "umk": "5acf31d0b22410.937575625acf31d0b"
}

newsletter/subscribed

{
  "timestamp": "2018-04-12T12:50:00+00:00",
  "optin_timestamp": "2018-04-12T12:55:00+00:00",
  "email": "john@doe.com",
  "signup_ip" : "1.2.3.4",
  "optin_ip": "1.2.3.4"
}

Sent when a customer's marketing preferences changes to "yes", either by signing up to a popup, by an API call, or by an admin in the app. signup_ip (optional) is the IP address used to initially sign up the user (might a server IP if this was an API call). optin_ip (optional) is the IP used to click the "confirm email" link in the double opt-in email, if sent.

sms/sent

{
  "timestamp": "2020-07-19T10:12:15.296Z",
  "email": "john@doe.com",
  "campaign_name": "Welcome Campaign",
  "campaign_id": "111112",
  "umk": "5acf31d0b22410.937575625acf31d0b",
  "characters_count": 92,
  "body": "Sample message content.",
  "to": "+15417540000",
  "from": "+15417541111",
  "is_test": false,
  "recipient_country_code": "US"
}

Sent when an SMS is sent to the recipient. campaign_id, campaign_name and umk are all optional fields, if the massage was sent by a system message (double opt-in confirmation, unsubscribe confirmation, etc.) these fields will not get included in the JSON.

sms/clicked

{
  "timestamp": "2020-07-19T10:12:15.296Z",
  "to": "+15417540000",
  "from": "+15417541111",
  "email": "john@doe.com",
  "campaign_name": "Welcome Campaign",
  "campaign_id": "111112",
  "umk": "5acf31d0b22410.937575625acf31d0b",
  "is_test": false,
  "ip": "1.1.1.1",
  "user_agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36",
  "url": "https://www.remarkey.com"
}

Sent when an SMS link with Remarkety's short URL was clicked. campaign_id, campaign_name and umk are all optional fields, if the massage was sent by a system message (double opt-in confirmation, unsubscribe confirmation, etc.) these fields will not get included in the JSON.

sms/replied

{
  "to": "+15417540000",
  "from": "+15417541111",
  "body": "Message content body"
}

Triggered when someone sends a message to one of your phone numbers that purchased via Remarkety.

sms/unsubscribed

{
    "timestamp": "2018-04-12T12:50:00+00:00",
    "email": "john@doe.com",
    "campaign_name": "Abandoned cart #1",
    "campaign_id": 11111,
    "umk": "5acf31d0b22410.937575625acf31d0b",
    "phone_number": "+15417543010",
    "reason": "Unsubscribed via link"
}

Sent whenever an SMS contact is unsubscribed, by replying to the account's incoming number or by clicking an unsubscribe link. campaign_id, campaign_name and umk are all optional fields, if the contact unsubscribed by replying to your incoming number, these fields will not get included in the JSON.

email-suppression/added

{
  "timestamp": "2018-04-12T12:50:00+00:00",
  "email": "john@doe.com",
  "client_ip": "1.1.1.1",
  "type": "unsubscribed",
  "reason": "Recipient unsubscribed"
}

Sent when an email is added to the suppression list and will not receive any marketing emails from now on.

The email address can be added multiple times to the suppression list with different suppression types.

Suppression types

email-suppression/removed

{
  "timestamp": "2018-04-12T12:50:00+00:00",
  "email": "john@doe.com",
  "client_ip": "1.1.1.1",
  "type": "unsubscribed",
  "reason": "Customer re-subscribed"
}

Sent when an email is removed from the suppression list.

The email address can be added multiple times to the suppression list with different suppression types, when a specific type is removed the email might still be in the list with a different suppression type.

Errors

The API may return the following error codes:

Error Code Meaning
400 Bad Request -- The request is malformed or is missing mandatory fields
401 Unauthorized -- Wrong API key
403 Forbidden
404 Not Found
406 Not Acceptable -- You requested a format that isn't json
418 I'm a teapot
429 Too Many Requests -- You are making too many requests in a limited time
500 Internal Server Error -- We had a problem with our server. Try again later.
503 Service Unavailable -- We're temporarily offline for maintenance. Please try again later.