Reporting Server-Side Events

Server-side Events for Track & Trigger


Using Server-Side Events

The Optimove server-side API allows you to send events that do not necessarily result directly from user activity in your website or mobile app. For example, changes in a player’s deposit balance or changes to a customer’s loyalty point balance.

Once properly implemented, your server can report nearly any event or user action to Optimove for storage, realtime analysis and campaign activation.


Enabling Optimove Server Side API

Optimove’s Product Integration Team will help you define the use cases to report to Optimove, allowing you to pre-configure your desired server-side events and their parameters before you begin reporting them to Optimove.

In order to implement server-side events:

  1. As part of the Track & Trigger onboarding, Optimove’s Product Integration Team will provide you with:
    • Optimove API Endpoint to be used for each API request
    • Optimove Tenant ID to use for each API request
    • Real-time token
  2. If you have not onboarded to Track & Trigger, please contact your Customer Success Manager (CSM) or other Optimove point of contact to request implementation of the server-side API for real-time in your Optimove site.
  3. Define the server-side events and parameters to be supported under the Events settings.
  4. Report events to Optimove by calling the API from your server-side code.

Events & Parameter

  1. The following parameter types are available for use in the events:
    • String – A series of alphanumeric characters of up to 255 characters in length, using any encoding
    • Number – Any numeric value, whether an integer or a value containing a decimal point
    • Boolean – Either true or false (not a string)
  2. Event and parameter names are case sensitive.
  3. Events and parameters use snakecase as a naming convention. Separate each word with one underscore character () and no spaces. (e.g., checkout_completed).
  4. All monetary values must be reported in the same currency defined in your Optimove instance (e.g., if your instance is based on US dollars, all monetary event values must be reported in US dollars). Optimove will not perform currency conversions.
  5. If your Optimove instance supports multiple languages, all event parameters must use a single default language. This is required in order to maintain a unified set of events.

Reporting Server-Side Events (V2)

Overview
Starting in Version 2 of the API (noted by the v2 path prefix), events sent to Optimove server side API should be sent using HMAC authorization.

Please make sure to follow the below steps after receiving your endpoint, token and tenant ID from Optimove’s Customer Solution Engineer Team:
Add the following headers to each request sent:

  1. X-Optimove-Signature-Content
    a. This header is an HMAC-SHA256 minified version of the request body
    b. The HMAC’s key is your Track & Trigger token that you receive from your Optimove Point of Contact.
    c. For example, to create this header in JS/TS use the below code snippet

🚧

minified = no whitespace & line break characters, no comments

  1. X-Optimove-Signature-Version = 1
function generateHash(trackAndTriggerToken: string, rawTextBody: Buffer | string) {
 return crypto.createHmac('sha256', trackAndTriggerToken)
  .update(Buffer.from(JSON.stringify(rawTextBody), 'utf-8'))
  .digest('hex');
}
import hashlib
import json

def generate_hash(track_and_trigger_token, raw_text_body):
    encoded_body = json.dumps(raw_text_body).encode('utf-8')
    hashed = hashlib.sha256(track_and_trigger_token.encode('utf-8'))
    hashed.update(encoded_body)
    return hashed.hexdigest()
static string GenerateHash(string trackAndTriggerToken, object rawTextBody)
    {
        string serializedBody = JsonConvert.SerializeObject(rawTextBody);
        byte[] encodedBody = Encoding.UTF8.GetBytes(serializedBody);
        byte[] tokenBytes = Encoding.UTF8.GetBytes(trackAndTriggerToken);
        using (var hmac = new HMACSHA256(tokenBytes))
        {
            byte[] hashBytes = hmac.ComputeHash(encodedBody);
            return BitConverter.ToString(hashBytes).Replace("-", "").ToLower();
        }
    }
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.util.Base64;

public class HMACExample {
    public static void main(String[] args) {
        try {
            // Sample JSON string (event payload with no whitespace & line break characters)
            String jsonString = "{\"name\":\"John\", \"age\":30, \"city\":\"New York\"}";

            // Your secret key (T&T token)
            String secretKey = "mySecretKey";

            // Create HMAC with SHA-256
            Mac mac = Mac.getInstance("HmacSHA256");

            // Initialize with the secret key
            SecretKeySpec secretKeySpec = new SecretKeySpec(secretKey.getBytes(StandardCharsets.UTF_8), "HmacSHA256");
            mac.init(secretKeySpec);

            // Compute the HMAC for the JSON string
            byte[] hmacBytes = mac.doFinal(jsonString.getBytes(StandardCharsets.UTF_8));

            // Convert HMAC bytes to Base64 or Hex
            String hmacBase64 = Base64.getEncoder().encodeToString(hmacBytes);
            // Optional: Convert to Hex if needed
            // String hmacHex = bytesToHex(hmacBytes);

            // Output the HMAC in Base64
            System.out.println("HMAC (Base64): " + hmacBase64);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    // Optional method to convert byte array to Hex string
    public static String bytesToHex(byte[] bytes) {
        StringBuilder hexString = new StringBuilder(2 * bytes.length);
        for (byte b : bytes) {
            String hex = Integer.toHexString(0xff & b);
            if (hex.length() == 1) {
                hexString.append('0');
            }
            hexString.append(hex);
        }
        return hexString.toString();
    }
}

Error Codes

  • If either header is missing, respond with a 422 Unprocessable Entity status and no HTTP body.
  • If the signature is invalid, respond with a 401 Unauthorized status and no HTTP body.

Server-side events must be reported using the following structure:

Body

{
    "tenant": int,
    "event": "string",
    "context": {
        "event_device_type": "string",
        "event_native_mobile": boolean,
        "event_platform": "string",
        "event_os": "string",
        "<param_key>": datatype according to configuration
    },
    "visitor": "string",
    "customer": "string",
    "timestamp": "DateTime"
}

Sample Request

{
    "tenant": 123,
    "event": "order",
    "context": {
        "event_device_type": "Web",
        "event_native_mobile": false,
        "event_platform": "iOS",
        "event_os": "iOS 13.5.0",
        "order_amount": 1000
    },
    "visitor": "5f6318f9dd72a705",
    "customer": "943437",
    "timestamp": "2020-05-26T07:40:45.495Z"
}

Headers

Content-Type = application/json
X-Optimove-Signature-Version = 1
X-Optimove-Signature-Content = <HMAC-SHA256 of the body>

Example
Given the example request body above, and a Track & Trigger token of '123456789', these are the expected headers (most notable, the X-Optimove-Signature-Content)

Content-Type = application/json
X-Optimove-Signature-Version = 1
X-Optimove-Signature-Content = a56995ec9935105c3261677dd7a0e19f1ce66ad594da9326cffbe6e74ac019e6

Important Notes:

  • **The request must contain EITHER a VisitorID or a CustomerID to identify the user, not both.
  • The CustomerID must match your Customer ID (CID) your are sending Optimove on a daily basis and is is also used to identify individual customer records within your Optimove customer database.
  • Event and parameter names are case sensitive.
  • The parameter types available for use in event-reporting functions will be dependent on the configuration within your Optimove instance.
  • All monetary values must be reported in the same currency defined in your Optimove instance (e.g., if your instance is based on US dollars, all monetary event values must be reported in dollars). Optimove will not perform currency conversions.
  • If your Optimove instance supports multiple languages, all event parameters must use a single default language. This is required in order to maintain a unified set of events.
  • If you are currently using Optimove’s Server Side API with no authorization and would like to add this method please contact your CSM or Optimove’s Customer Solution Engineer Team.

Sequential Events

Triggered campaigns are activated when a visitor or a customer sets off a Trigger. Triggers are built, within the Optimove platform, with events. Triggers can be defined as activated either by events that arrive in a specific sequence or events that arrive in any given order.

For Triggers that are activated by events that arrive in a specific sequence, it is important that Optimove receives the relevant events in the same order as defined within the Trigger.

In order to ensure the correct order of arrival, you may send the relevant events as part of the same request, within an array, like so:

[
    {
        "tenant": int,
        "event": "<event_key>",
        "context": {
            "event_device_type": "Mobile/Web",
            "event_native_mobile": true, // false,
            "event_platform": "<platform Ex. iOS/Android>",
            "event_os": "<operating system Ex. iOS 13.5.0>",
            "<param_key>": "<param_value>"
        },
        "visitor": "<visitorid>",
        "customer": "<customerid>",
        "timestamp": "<event timestamp Ex. 2020-05-26T07:40:45.495Z>"
    },
    {
        "tenant": int,
        "event": "<event_key>",
        "context": {
            "event_device_type": "Mobile/Web",
            "event_native_mobile": true, // false,
            "event_platform": "<platform Ex. iOS/Android>",
            "event_os": "<operating system Ex. iOS 13.5.0>",
            "<param_key>": "<param_value>"
        },
        "visitor": "<visitorid>",
        "customer": "<customerid>",
        "timestamp": "<event timestamp Ex. 2020-05-26T07:40:45.495Z>"
    }
]

The events will then be received by Optimove in the order in which they appear in the array.


Server-Side Rate Limit

Our server is limited to processing 1,000 requests per second, with each request capable of containing a maximum of 10 events.

Notes:

  • It is possible to include up to 10 events, each associated with a different customer ID, within a single request.

Basic events

Optimove has a set of basic events that are recommended to be used, once received, instruct the Optimove system to perform actions that are key to ensure correct identity resolution and campaign execution:

  1. Set page visit
  2. Set email event
  3. Registration
  4. Login

Pre-defined events notes:

  • Set user ID event is a pre-defined event; however, in the latest version you are not required to use it to update Optimove when a visitor converts to a customer. You can notify Optimove by adding the customer ID to each custom event you report.
  • Set page visit and set email event are pre-defined events and preconfigured within your Optimove instance. There is no need to manually configure pre-defined events.
  • Pre-defined events cannot contain any additional custom parameters.

Set Email Event

This pre-defined event attaches an email address to a visitor or a customer entity in real-time. After reporting this event, a visitor/customer may be targeted by an email execution channel.

Event structure:

{  
    "tenant": int,  
    "event": "set_email_event",  
    "context": {  
        "event_device_type": "Mobile/Web",  
        "event_native_mobile": true, // false,  
        "event_platform": "\<platform Ex. iOS/Android>",  
        "event_os": "\<operating system Ex. iOS 13.5.0>",  
        "email": "<email>"  
    },  
    "visitor": "<visitorid>",  
    "customer": "<customerid>",  
    "timestamp": "\<event timestamp Ex. 2020-05-26T07:40:45.495Z>"  
}

For set email events, "email" is a mandatory parameter and should be a valid email address.

Set Page Visit

This pre-defined event notifies the Optimove system that a visitor/customer has visited a page within your website.

Event structure:

{  
    "tenant": int,  
    "event": "set_page_visit",  
    "context": {  
        "event_device_type": "Mobile/Web",  
        "event_native_mobile": true, // false,  
        "event_platform": "\<platform Ex. iOS/Android>",  
        "event_os": "\<operating system Ex. iOS 13.5.0>",  
        "customURL": "<URL>",  
        "pageTitle": "<pageTitle>",  
        "category": "<category>"  
    },  
    "visitor": "<visitorid>",  
    "customer": "<customerid>",  
    "timestamp": "\<event timestamp Ex. 2020-05-26T07:40:45.495Z>"  
}

For set page visit events, "customURL", and "pageTitle" are mandatory parameters.

Registration

Optimove distinguishes between unknown website visitors, website visitors that have converted today, and customers.

Unknown website visitors are entities that are allocated a temporary ID, in the case of server-side events, by a system external to Optimove.
(visitor ID management by Optimove is supported only by implementing Optimove’s SDK).

Customers are entities that are allocated a customer ID by a system external to Optimove. The bulk of the information related to these customers is received through the daily ETL process.

Visitors that have converted today are entities that are in transition between the two states above. Information on these entities has not yet been received through the daily ETL, however, a customer ID has been allocated.

Whenever a NEW customer ID is sent as part of an event, Optimove system recognizes that a visitor has been converted into a customer. These customers can be targeted with a Triggered Campaign under the Visitor target group called “Converted Today”. The days following the conversion, these users can be targeted under any Customer target groups.

Whenever a single user action requires a new registration (e.g., registration, newsletter signup), we suggest using the registration event

Event structure:

{
        "tenant": int,
        "event": "registration",
        "context": {
            "event_device_type": "Mobile/Web",
            "event_native_mobile": true, // false,
            "event_platform": "<platform Ex. iOS/Android>",
            "event_os": "<operating system Ex. iOS 13.5.0>",
            "email": "[email protected]",
            "first_name": "<firstName>",
            "opt_in": true, // false	
        },
        "visitor": "<visitorid>",       
        "customer": "<customerid>",
        "timestamp": "<event timestamp Ex. 2020-05-26T07:40:45.495Z>"
    }

Login

In all cases, where you detect a user login call the login event

Event structure:

{
        "tenant": int,
        "event": "login",
        "context": {
            "event_device_type": "Mobile/Web",
            "event_native_mobile": true, // false,
            "event_platform": "<platform Ex. iOS/Android>",
            "event_os": "<operating system Ex. iOS 13.5.0>",
            "brand": "<brand>"
 
        },
        "visitor": "<visitorid>",       
        "customer": "<customerid>",
        "timestamp": "<event timestamp Ex. 2020-05-26T07:40:45.495Z>"
    }


Visitor Management for Server-Side Events

When implementing T&T using server-side events, Optimove is not the entity generating visitor IDs.

You may still accumulate data and target visitors with Triggered Campaigns, however, the visitor ID management must be taken care of independently and external to Optimove.

Targeting visitors by Email

Whenever the website captures a visitor’s email address, such as when a visitor submits a newsletter you can call a custom event that includes the ‘email’ parameter. After using a custom event including email parameter the visitor may be targeted by an email execution channel

{
        "tenant": int,
        "event": "newsletter_reg",
        "context": {
		"event_device_type": "Mobile/Web",
		"event_native_mobile": true, // false,
		"event_platform": "<platform Ex. iOS/Android>",
		"event_os": "<operating system Ex. iOS 13.5.0>",
		"brand": "<brand>"
		"email": "<email>"
			
 
        },
        "visitor": "<visitorid>",       
        "timestamp": "<event timestamp Ex. 2020-05-26T07:40:45.495Z>"
    }

Notes:

  • Should you decide to manage the visitor’s identity on your server/backend, in order to ensure events are correlated correctly, visitorID consistency must be maintained when sending different events generated by the same visitor.
  • Upon visitor conversion, in order to ensure events, that were generated while in a visitor state, are correctly attached to the customer, an event including customer ID must be sent with the correct mapping between the visitor and customer IDs.
  • Visitor IDs must be less than 200 characters
  • The "email" is a required variable and must be a "string" format.
  • Make sure the email is valid.

Consent Management Event<a id="consent>

This event provides the ability to update the subscription status of each customer in realtime. After reporting this event, your customers' subscription status will be updated in the SendGrid suppression list (includes or excludes the relevant email address) and in the OptiMail unsubscribe attribute.

Event structure:

{
    "tenant":int,
    "event": "consent",
    "context": {
        "brand": "brand id",
        "opt_in": false/true,
        "identifier": "email",
        "event_origin": "server",
        "execution_method": "email",
        "channel_id": 15
    },
    "customer": "<customerid>"
}

Important notes:

  • All parameters in the structure are mandatory
  • The brand ID and the tenant's Id can be provided by your CSM
  • Event and parameter names are case sensitive.

Server side response

Status code familyMeaningHandling
2xxThe event has been processed successfullyNothing
4xxThere was a problem with the request.Check the request on your side.
5xxThere was a problem while processing the requestTry again in 30 seconds.