Tracking events

There are two ways to track data: Through front-end or back-end.
Front-end means that you will use a tracking pixel on your website. Back-end means you use server to server communication to track your data via our API.

The goal is to send events to us with user behavior, so we can create segments that you can use on the connected channels.
This integration guide will help you set up the event tracking.

Front-end tracking

Almost all tracking will be done through front-end.

Place the following personalized code snippet in the head section of every page you want to use tracking on.


    <script type="text/javascript">

     (function(s,q,z,l,y){s._sqzl=s._sqzl||[];l=q.createElement('script'),
     y=q.getElementsByTagName('script')[0];l.async=1;l.type='text/javascript';
     l.defer=true;l.src=z;y.parentNode.insertBefore(l,y)})
     (window,document,'https://squeezely.tech/tracker//sqzl.js');

    </script>
        

Tracking events

You can track Standard Events or Custom Events.
For example. if you want to track a pageview through the standard PageView event, use the following code:

    <script type="text/javascript">

        window._sqzl = window._sqzl || [];

        window._sqzl.push({
            "event" : "PageView"
        });

    </script>
                            

That's all, your visitors are now being tracked!
The more info we have the better your segments will be. To provide more data, use the available properties as shown in the documentation of the event.

Another example: Track a Purchase event:

<script type="text/javascript">

    window._sqzl = window._sqzl || [];

    window._sqzl.push({
      "event"         : "Purchase",
      "email"         : "jan@schmit.com",
      "firstname"     : "Jan",
      "lastname"      : "Schmidt",
      "gender"        : "M",
      "birthdate"     : "1985-12-31",
      "city"          : "Berlin",
      "country"       : "DE",
      "orderid"       : "12345",
      "currency"      : "EUR",
      "products"      : [{
          "id": "ABC123",
          "name": "Product 1",
          "price": 29.99,
          "quantity": 2
        }]
    });

</script>
                                    

All events work this way, you can track as many events on a page as you want. Please refer to the event specific documentation (found in the menu on the left) to find out which events and properties are supported.

Event: PageView

Event should be fired when someone views a page.
Note: This event must be implemented on all pages, regardless if other events are triggered.

Available properties:
Name Description
event PageView Mandatory
campaign The identifier for this campaign. If this is in the url of your landing page as variable sqzl_campaign or utm_campaign, you can omit this. Saved in client session. Optional
source Source of the customer (e.g. facebook or Google Ads). If this is in the url of your landing page as variable sqzl_source or utm_source, you can omit this. Saved in client session. Optional

Event: Purchase

Event should be fired when someone makes a purchase.

Available properties:
Name Description
event Purchase Mandatory
email Customer email or SHA256 of the email Mandatory
orderid Order reference of the purchase. Used to calculate revenue correctly. Mandatory
firstname Customer first name Mandatory
lastname Customer last name Mandatory
userid User id or username of the customer. Your unique identifier for the customer. Optional
campaign The identifier for this campaign. If this is in the url of your landing page as variable sqzl_campaign or utm_campaign, you can omit this. Saved in client session. Optional
source Source of the customer (e.g. facebook or adwords). If this is in the url of your landing page as variable sqzl_source or utm_source, you can omit this. Saved in client session. Optional
gender Customer gender (M/F/U) Optional
birthdate Customer birthdate (yyyy-mm-dd) Optional
phone Customer phone Optional
postcode Customer postcode Optional
city Customer city Optional
country Customer 2-letter country code (e.g. NL, ISO 3166-1 alpha-2) Optional
currency Currency of the purchase (e.g. GBP/EUR/USD, ISO 4217) Optional
newsletter Has the user opted in for email/newsletter. Correct value are yes or no. If you don't know, don't send this field. Optional
products JSON array of product(s). Supported properties:

id unique id or SKU. Mandatory
name name of the product.
price Price of the single product, 2 decimals.
quantity Quantity bought. Defaults to 1.
Example 1:
  [{"id": "ABC123"}]
Example 2:
[
    {
        "id": "ABC123",
        "name": "Product 1",
        "price": 29.99,
        "quantity": 2
    },
    {
        "id": "XYZ_789",
        "name": "Product 2",
        "price": 39.99,
        "quantity": 1
    }
]
Mandatory

Event: PrePurchase

Fire the PrePurchase event when a user has shared details with you, but still has to confirm the payment.
For example fire the event just before a customer is redirected to an external payment environment.

Note: The PrePurchase event is not mandatory, however we highly recommend using it. Implementing this event will give you more accurate sales tracking and more complete profile information.

Available properties:
Name Description
event PrePurchase Mandatory
campaign The identifier for this campaign. If this is in the url of your landing page as variable sqzl_campaign or utm_campaign, you can omit this. Saved in client session. Optional
source Source of the customer (e.g. facebook or Google Ads). If this is in the url of your landing page as variable sqzl_source or utm_source, you can omit this. Saved in client session. Optional
email Customer email or SHA256 of the email Mandatory
userid User id or username of the customer. Your unique identifier for the customer. Optional
firstname Customer first name Mandatory
lastname Customer last name Mandatory
gender Customer gender (M/F/U) Optional
birthdate Customer birthdate (yyyy-mm-dd) Optional
phone Customer phone Optional
postcode Customer postcode Optional
city Customer city Optional
country Customer 2-letter country code (e.g. NL, ISO 3166-1 alpha-2) Optional
orderid Order reference of the purchase. Used to calculate revenue correctly. Optional
currency Currency of the purchase (e.g. GBP/EUR/USD, ISO 4217) Optional
newsletter Has the user opted in for email/newsletter. Correct value are yes or no. If you don't know, don't send this field. Optional
products JSON array of product(s). Supported properties:

id unique id or SKU. Mandatory
name name of the product.
price Price of the single product, 2 decimals.
quantity Quantity bought. Defaults to 1.
Example 1:
  [{"id": "ABC123"}]
Example 2:
[
    {
        "id": "ABC123",
        "name": "Product 1",
        "price": 29.99,
        "quantity": 2
    },
    {
        "id": "XYZ_789",
        "name": "Product 2",
        "price": 39.99,
        "quantity": 1
    }
]
Optional

Event: AddToCart

Event should be fired when someone adds something to their cart.

Available properties:
Name Description
event AddToCart Mandatory
campaign The identifier for this campaign. If this is in the url of your landing page as variable sqzl_campaign or utm_campaign, you can omit this. Saved in client session. Optional
source Source of the customer (e.g. facebook or Google Ads). If this is in the url of your landing page as variable sqzl_source or utm_source, you can omit this. Saved in client session. Optional
currency Currency of the product (e.g. GBP/EUR/USD) Optional
products JSON array of product(s). Supported properties:

id unique id or SKU. Mandatory
name name of the product.
price Price of the single product, 2 decimals.
quantity Quantity bought. Defaults to 1.
Example 1:
  [{"id": "ABC123"}]
Example 2:
[
    {
        "id": "ABC123",
        "name": "Product 1",
        "price": 29.99,
        "quantity": 2
    },
    {
        "id": "XYZ_789",
        "name": "Product 2",
        "price": 39.99,
        "quantity": 1
    }
]
Mandatory

Event: ViewContent

Event should be fired when someone visits a product page on your website.

Available properties:
Name Description
event ViewContent Mandatory
campaign The identifier for this campaign. If this is in the url of your landing page as variable sqzl_campaign or utm_campaign, you can omit this. Saved in client session. Optional
source Source of the customer (e.g. facebook or Google Ads). If this is in the url of your landing page as variable sqzl_source or utm_source, you can omit this. Saved in client session. Optional
currency Currency of the product (e.g. GBP/EUR/USD) Optional
products JSON array of product(s). Supported properties:

id unique id or SKU. Mandatory
name name of the product.
price Price of the single product, 2 decimals.
Example 1:
  [{"id": "ABC123"}]
Example 2:
[
    {
        "id": "ABC123",
        "name": "Product 1",
        "price": 29.99
    },
    {
        "id": "XYZ_789",
        "name": "Product 2",
        "price": 39.99
    }
]
Mandatory

Event: ViewCategory

Event should be fired when someone views a category page.

Available properties:
Name Description
event ViewCategory Mandatory
category_id Id of the viewed category (e.g. ABC123) Mandatory
campaign The identifier for this campaign. If this is in the url of your landing page as variable sqzl_campaign or utm_campaign, you can omit this. Saved in client session. Optional
source Source of the customer (e.g. facebook or adwords). If this is in the url of your landing page as variable sqzl_source or utm_source, you can omit this. Saved in client session. Optional
objectname Name of the viewed category Optional
products JSON array of product(s). Supported properties:

id unique id or SKU. Mandatory
name name of the product.
price Price of the single product, 2 decimals.
Example 1:
  [{"id": "ABC123"}]
Example 2:
[
    {
        "id": "ABC123",
        "name": "Product 1",
        "price": 29.99
    },
    {
        "id": "XYZ_789",
        "name": "Product 2",
        "price": 39.99
    }
]
Optional

Event: Custom PRO

You can add a custom event to target people with certain website behavior.

Available properties:
Name Description
event Your custom event Mandatory
campaign The identifier for this campaign. If this is in the url of your landing page as variable sqzl_campaign or utm_campaign, you can omit this. Saved in client session. Optional
source Source of the customer (e.g. facebook or adwords). If this is in the url of your landing page as variable sqzl_source or utm_source, you can omit this. Saved in client session. Optional
value Value of your custom event Optional

Event: Lead

You can add a lead event to target people who sign up.

Available properties:
Name Description
event Lead Mandatory
campaign The identifier for this campaign. If this is in the url of your landing page as variable sqzl_campaign or utm_campaign, you can omit this. Saved in client session. Optional
source Source of the customer (e.g. facebook or adwords). If this is in the url of your landing page as variable sqzl_source or utm_source, you can omit this. Saved in client session. Optional
value Value of your lead event Optional

Event: EmailOptIn

Event should be fired when someone subscribes to or unsubscribes from your newsletter, marketing or service e-mails.

Available properties:
Name Description
event EmailOptIn Mandatory
email Customer email or SHA256 of the email Optional
newsletter Is the user opt-in for newsletters. Correct value are yes or no. If you don't know, don't send this field. Mandatory
marketing Is the user opt-in for marketing letters. Correct value are yes or no. If you don't know, don't send this field. Optional
service Is the user opt-in for service messages. Correct value are yes or no. If you don't know, don't send this field. Optional

Event: CompleteRegistration

Event should be fired when someone completes a registration/signup form.

Available properties:
Name Description
event CompleteRegistration Mandatory
campaign The identifier for this campaign. If this is in the url of your landing page as variable sqzl_campaign or utm_campaign, you don't have to pass this. Saved in client session. Optional
source Source of the customer (e.g. facebook or adwords). If this is in the url of your landing page as variable sqzl_source or utm_source, you don't have to pass this. Saved in client session. Optional

Event: InitiateCheckout

Event should be fired when someone starts the checkout flow.

Available properties:
Name Description
event InitiateCheckout Mandatory
email Customer email or SHA256 of the email Optional
firstname Customer first name Optional
lastname Customer last name Optional
userid User id or username of the customer. Your unique identifier for the customer. Optional
campaign The identifier for this campaign. If this is in the url of your landing page as variable sqzl_campaign or utm_campaign, you can omit this. Saved in client session. Optional
source Source of the customer (e.g. facebook or Google Ads). If this is in the url of your landing page as variable sqzl_source or utm_source, you can omit this. Saved in client session. Optional
gender Customer gender (M/F/U) Optional
birthdate Customer birthdate (yyyy-mm-dd) Optional
phone Customer phone Optional
postcode Customer postcode Optional
city Customer city Optional
country Customer 2-letter country code (e.g. NL, ISO 3166-1 alpha-2) Optional
currency Currency of the purchase (e.g. GBP/EUR/USD, ISO 4217) Optional
newsletter Has the user opted in for email/newsletter. Correct value are yes or no. If you don't know, don't send this field Optional
products JSON array of product(s). Supported properties:

id unique id or SKU. Mandatory
name name of the product
price Price of the single product, 2 decimals. Mandatory
quantity Quantity bought. Defaults to 1.
Example 1:
  {"id": "ABC123", "price": 29.99}
Example 2:
[
    {
        "id": "ABC123",
        "name": "Product 1",
        "price": 29.99,
        "quantity": 2
    },
    {
        "id": "XYZ_789",
        "name": "Product 2",
        "price": 39.99,
        "quantity": 1
    }
]
Mandatory

Contacts

It is not needed to create new contacts.
When an event contains an email address, userid, or cookie we don't know or can't connect to an existing user, we will create a new contact.

If you want to add a contact to Squeezely, but there is no user activity like a PageView, send a CRMUpdate event through our backend(!) API.

Callback

It's possible to add a callback to the frontend tracking pixel.

Callback per event
You can set a callback per event send through the frontend tracking pixel. Using the following code:

    <script type="text/javascript">

        _sqzl.push({
            "event" : "PageView",
            "callback": function(eventData) {
                // This function is called whenever the img pixel is finished
                // eventData contains the event Object
            }
        });

    </script>
                            

Callback on all events
It's also possible to hook on all events and register a callback for that. Using the following code:

    <script type="text/javascript">

        _sqzl.push({
            "SetCallback" : function(eventData) {
                // This function is called whenever the img pixel is finished
                // eventData contains the event Object
            }
        });

    </script>
                            

Using the back-end API


This API is meant for server to server HTTP calls.

Authentication

All API endpoints require authentication. Authentication will be performed by checking two values in the HTTP request headers.
Header Description
X-AUTH-ACCOUNT This is the Account-identifier
X-AUTH-APIKEY This is the secret API key. Consider this value as being a password.

The API key can be found and if so desired, modified in the settings panel.

Data formatting

All information sent to the API has to be in either or JavaScript Object Notation (JSON) format or included as HTTP POST parameters. Responses will always be in JSON format. We currently do not support other formats like XML or other methods of serialization.

Base API URL

All back-end API endpoints can be reached at https://squeezely.tech

Example requests

PHP


    $url = "https://squeezely.tech/api/v1/<ENDPOINT>";
    $fields = [
        "some_field" => "some_value"
    ];
    $json = json_encode($fields);

    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $json);
    curl_setopt($ch, CURLOPT_HTTPHEADER, [
        "X-AUTH-ACCOUNT: <ACCOUNT_IDENTIFIER>",
        "X-AUTH-APIKEY: <API_KEY>",
        "Content-Type: application/json",
        "Content-Length: " . strlen($json)
    ]);
    
    $result = curl_exec($ch);
    curl_close($ch);



Response values

When correctly authorized, we will return a JSON response with the result.

Example response for a correct call:
{
    "success": true,
    // ...
    "errors": []
}

Example response for an incorrect call:
{
    "success": false,
    "errors": [
        // ...
    ]
}

Response codes


HTTP status code Description Error codes
403 Invalid credentials MISSING_API_KEY_OR_ACCOUNT
INVALID_CREDENTIALS
MISSING_ACCOUNT_ACTIVE_USER

Back-end Tracking


With backend tracking you can send server to server events.

Backend events have the same parameters as frontend events, but also allow you to set the date & time.
You can send up to 250 events at a time. See the PHP example code below:

    $url = "https://squeezely.tech/api/v1/track";
    $fields = [
        "events" => [
             [
                 "event"           => "Purchase",
                 "email"           => $email,
                 "firstname"       => $firstname,
                 "lastname"        => $lastname,
                 "gender"          => $order->getCustomerGender(),
                 "birthdate"       => $order->getCustomerDob(),
                 "phone"           => $order->getShippingAddress()->getTelephone(),
                 "postcode"        => $order->getShippingAddress()->getPostcode(),
                 "city"            => $order->getShippingAddress()->getCity(),
                 "country"         => $order->getShippingAddress()->getCountry(),
                 "currency"        => $order->getOrderCurrencyCode(),
                 "orderid"         => $orderId,
                 "newsletter"      => $newsletterOptin ? "yes" : "no",
                 "marketingletter" => $marketingletterOptin ? "yes" : "no",
                 "serviceletter"   => $serviceletterOptin ? "yes" : "no",
                 "products"        => [
                     [
                         "id" => "ABC123",
                         "name" => "Product 1",
                         "category_id" => "CAT_1",
                         "price" => 29.99,
                         "quantity" => 2
                     ],
                     [
                         "id" => "XYZ_789",
                         "name" => "Product 2",
                         "category_id" => "CAT_2",
                         "price" => 39.99,
                         "quantity" => 1
                     ]
                 ]
            ]
        ]
    ];

    $json = json_encode($fields);

    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $json);
    curl_setopt($ch, CURLOPT_HTTPHEADER, [
        "X-AUTH-ACCOUNT: <ACCOUNT_IDENTIFIER>",
        "X-AUTH-APIKEY: <API_KEY>",
        "Content-Type: application/json",
        "Content-Length: " . strlen($json)
    ]);
    
    $result = curl_exec($ch);
    curl_close($ch);
                                    

Just replace the values with your values and you're ready to go!

Response values

When correctly authorized, we will return a JSON response with the result.

API Response when the request has been handled successfully:
{
    "success": true,
    "count": 12,
    "errors": []
}

API Response when the request has not been handled successfully:
{
    "success": false,
    "count": 0,
    "errors": [
        "NO_EMAIL_OR_USERID"
    ]
}

API Response when the request has duplicate events:
{
    "success": false,
    "count": 0,
    "duplicate_count": 1,
    "errors": [
        "DUPLICATE_EVENT"
    ]
}

Response codes


HTTP status code Description Error codes
201 Resource created (partially) NO_EMAIL_OR_USERID
NO_MERCHANT
UNKNOWN_ERRROR
400 No resource created NO_EVENTS
TOO_MANY_EVENTS
NO_EMAIL_OR_USERID
NO_MERCHANT
UNKNOWN_ERRROR
DUPLICATE_EVENT

Event: Purchase

Endpoint: /api/v1/trackPOST

Event should be fired when someone makes a purchase.

Available properties:
Name Description
event Purchase Mandatory
email Customer email or SHA256 of the email Mandatory
firstname Customer first name Mandatory
lastname Customer last name Mandatory
orderid Order reference of the purchase. Used to calculate revenue correctly. Mandatory
timestamp Timestamp of the event, only needed for events in the past. Formats allowed: unix epoch timestamp or yyyy-mm-dd Optional
userid User id or username of the customer. Your unique identifier for the customer. Optional
gender Customer gender (M/F/U) Optional
birthdate Customer birthdate (yyyy-mm-dd) Optional
phone Customer phone Optional
postcode Customer postcode Optional
city Customer city Optional
country Customer 2-letter country code (e.g. NL, ISO 3166-1 alpha-2) Optional
currency Currency of the purchase (e.g. GBP/EUR/USD, ISO 4217) Optional
newsletter Has the user opted in for email/newsletter. Correct value are yes or no. If you don't know, don't send this field. Optional
products Array of product(s). Supported properties:

id unique id or SKU. Mandatory
name name of the product
price Price of the single product, 2 decimals. Mandatory
quantity Quantity bought. Defaults to 1.
Example 1:
  ["id" => "ABC123", "price" => 29.99]
Example 2:
[
    [
        "id" => "ABC123",
        "name" => "Product 1",
        "price" => 29.99,
        "quantity" => 2
    ],
    [
        "id" => "XYZ_789",
        "name" => "Product 2",
        "price" => 39.99,
        "quantity" => 1
    ]
]
Mandatory
campaign The identifier for this campaign. If this is in the url of your landing page as variable sqzl_campaign or utm_campaign, you can omit this. Saved in client session. Optional
source Source of the customer (e.g. facebook or Google Ads). If this is in the url of your landing page as variable sqzl_source or utm_source, you can omit this. Saved in client session. Optional

Response codes

HTTP status code Description Error codes
201 Resource created (partially) NO_EMAIL_OR_USERID
NO_MERCHANT
UNKNOWN_ERRROR
400 No resource created NO_EVENTS
TOO_MANY_EVENTS
NO_EMAIL_OR_USERID
NO_MERCHANT
UNKNOWN_ERRROR
DUPLICATE_EVENT

Products

Create or update up to 250 products at a time through our API:

Endpoint: /api/v1/productsPOST

Name Description
products Array of product(s) you want to add/update. Supported properties:

id unique id or SKU Mandatory
title title of the product Mandatory
link URL of the product Mandatory
description Product description
language Default: EN
Currently supported: EN, DE, ES, FR, NL, JP, NO, PL, TR
price 2 decimals, no thousands-separator. Optionally add currency. examples: 1099.99 or EUR 99.01 or 99 EUR
currency Currency e.g. GBP, EUR, USD
image_link URL of the image
image_links Array of image URLs. Supply up to 20 images. (Overwrites image_link field)
availability in stock (default), out of stock, available for order, preorder
condition new (default), used, refurbished
inventory Amount of products in stock
brand Brand of the product
parent_id Products with the same parent id / parent SKU will be grouped as variants in your catalog
category_ids Array of category ids / SKUs. Categories that contain this product.
google_product_category Include either numerical category ID (preferred) or the full path of the Google category.
Please refer to the Google Product Taxonomy documentation.
date_availability Availablity for travel, see more.
Array of all current product date availabilities (max 180 days), previously supplied availability will be erased.
[
    {
        "checkin" : "2019-09-23",
        "nights" : 7
    },
    {
        "checkin" : "2019-09-23",
        "nights" : 6
    },
]
Example request:
{
    "products": [
        {
            "id" : "ABC123",
            "title" : "Product 1",
            "link" : "https://yourshop.com/product-1"
        },
        {
            "id" : "XYZ_789",
            "title" : "Product 2",
            "link" : "https://yourshop.com/product-2",
            "description" : "Product 2 description",
            "price" : "GBP 19.95",
            "image_link" : "https://yourshop.com/product-2.jpg",
            "condition" : "new",
            "inventory" : 80,
            "brand" : "Your brand",
            "parent_id" : "XYZ",
            "category_ids": ["CAT-123", "CAT-321"]
        }
    ]
}

Example success response:
{
    "success": true,
    "created": 1,
    "updated": 1,
    "errors": []
}

Example error response (2 products with missing title):
{
    "success": false,
    "errors": [
        "#0: no title",
        "#1: no title"
    ]
}

Example error response (2 products, 1 with incorrect condition):
{
    "success":true,
    "created": 1,
    "updated": 0,
    "errors": [
        "#1: condition not correct"
    ]
}
Mandatory

Response codes

HTTP status code Description Error codes
201 Resource created
400 No resource created WRONG_CONTENTTYPE, NO_PRODUCTS, TOO_MANY_PRODUCTS,

Categories

Create or update up to 250 categories at a time through our API:

Endpoint: /api/v1/categoriesPOST

Name Description
categories Array of categories you want to add/update. Supported properties:

category_id unique id or SKU Mandatory
title title of the category Mandatory
description Description of the category
link URL of the category
Example request:
{
    "categories": [
        {
            "category_id" : "CAT_1",
            "title" : "Category 1"
        },
        {
            "category_id" : "CAT_2",
            "title" : "Category 2",
            "link" : "https://yourshop.com/category-2",
            "description" : "Category 2 description"
        }
    ]
}

Example success response:
{
    "success": true,
    "created": 1,
    "updated": 1,
    "errors": []
}

Example error response (2 categories with missing title):
{
    "success": false,
    "errors": [
        "#0: no title",
        "#1: no title"
    ]
}
Mandatory

Response codes

HTTP status code Description Error codes
201 Resource created
400 No resource created WRONG_CONTENTTYPE, NO_CATEGORIES, TOO_MANY_CATEGORIES,

Reporting

You can the export data you collected with Squeezely.
Call the resource endpoint and we will generate a CSV file.
Optionally you can supply a callback url which we call when the file is generated.
CSV files are purged after 7 days.

Example request:


    $url = "https://api.squeezely.tech/v1/reporting/events";
    $fields = [
        "from" => "2018-01-01",
        "to" => "2018-02-01"
    ];
    $json = json_encode($fields);

    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($fields));
    curl_setopt($ch, CURLOPT_HTTPHEADER, [
        "X-AUTH-ACCOUNT: <ACCOUNT_IDENTIFIER>",
        "X-AUTH-APIKEY: <API_KEY>",
        "Content-Type: application/json",
        "Content-Length: " . strlen($json)
    ]);
        
    $result = curl_exec($ch);
    curl_close($ch);

                                
Example response:
{
    "success": true,
    "url": "https://api.squeezely.tech/v1/reporting/download/cf2acd31eac8c5288f05dd6366dc1e4f.csv"
}

Available reports



Response codes

HTTP status code Description Error codes
201 Resource created
400 No resource created REPORTING_NOT_ENABLED, UNKNOWN_ERROR

Events export

Endpoint: /api/v1/reporting/eventsPOST

You can use these filters:
Name Description
from YYYY-mm-dd or Unix epoch timestamp. Mandatory
to YYYY-mm-dd or Unix epoch timestamp. Mandatory
custom_fields Whether to export custom fields. Correct value are yes (default) or no. Optional
callback_url URL we call once when the file is available for download. Optional

Response codes

HTTP status code Description Error codes
201 Resource created
400 No resource created REPORTING_NOT_ENABLED, NO_JSON_PARAMETER_SUPPORT, NO_DATE_RANGE_PROVIDED, INVALID_FROM_DATE, INVALID_TO_DATE, UNKNOWN_ERROR

CSV content


NOTE: The field order is not guaranteed. Please map to the correct fields by using the field names in the first row of the CSV file.
The following fields can be expected in a report after it has been generated and downloaded:
Field name Description
id Unique identifier for this event
event Event name or Unknown if not known
created_at Event date & time (e.g. yyyy-mm-dd HH:ii:ss)
platform The platform. (e.g. android, ios, iphone, ipad, mac, unix, widows)
url The URL the event was triggered on
source The source sent with the event. (e.g. facebook)
api This event was received via our API. Values: 0 or 1
cookie A string value that identifies a contact
customer_id Unique identifier for this contact
userid Your unique user identifier
email Contact email
firstname Contact first name
lastname Contact last name
gender Contact gender. Value as sent in the event.
birthdate Contact birthdate (yyyy-mm-dd, 0000-00-00 if unknown)
phone Contact phone
city Contact city
country Contact country
offlinelocation A location if a purchase was done offline
totalvalue Total value of a purchase
products JSON array of product(s)
category_id Id of a viewed category (e.g. ABC123)
objectname Name of the viewed category
currency Currency of the contact (e.g. GBP/EUR/USD)
orderid The order id
utm_campaign The event UTM campaign
utm_source The event UTM source
sqzl_campaign The event squeezely campaign
sqzl_source The event squeezely source
keyword The keyword received in the event
value The value of a custom event
ip The IP address the event was received from
custom_fields JSON array of custom fields
device The contact's device type. Values: mobile, desktop

Contacts export

Endpoint: /api/v1/reporting/contactsPOST

You can use these filters:
Name Description
userids Comma separated list of your unique user identifier(s) of the contacts you want to select. Optional
emails Comma separated list of emails of the contacts you want to select. Optional
custom_fields Whether to export custom fields. Correct value are yes (default) or no. Optional
callback_url URL we call once when the file is available for download. Optional

Response codes

HTTP status code Description Error codes
201 Resource created
400 No resource created REPORTING_NOT_ENABLED, NO_JSON_PARAMETER_SUPPORT, UNKNOWN_ERROR

CSV content


NOTE: The field order is not guaranteed. Please map to the correct fields by using the field names in the first row of the CSV file.
The following fields can be expected in a report after it has been generated and downloaded:
Field name Description
id Unique identifier for this contact
userid Your unique user identifier
cookie Contact cookie
email Contact email
email_hash A sha256 hash of the email
Please replace this field with the new emailhash field
Deprecated
firstname Contact first name
lastname Contact last name
gender Contact gender (M/F/U)
birthdate Contact birthdate (yyyy-mm-dd)
phone Contact phone
zipcode Contact zipcode
city Contact phone
country Contact 2-letter country code (e.g. NL, ISO 3166-1 alpha-2)
currency Currency of the contact (e.g. GBP/EUR/USD)
optin Has the contact opted in for newsletters. Values: yes or no.
Please replace this field with the new newsletter field
Deprecated
emailhash A sha256 hash of the email
newsletter Has the contact opted in for newsletters. Values: yes or no.
marketing Has the contact opted in for marketing emails. Values: yes or no.
service Is the user opt-in for service emails. Values: yes or no.

Download an export

Endpoint: /api/v1/reporting/download/XXX.csvGET

Use this endpoint to download a previously created report.

Response codes

HTTP status code Description Error codes
200 OK
404 Resource not available RESOURCE_NOT_FOUND, RESOURCE_NOT_READY, RESOURCE_EXPIRED

Privacy requests

Conforming with the European General Data Protection Regulation law, known as GDPR has become mandatory.

By implementing this server to server API endpoint it is possible to give customers a custom experience when giving insight to the personal information that has been stored. Implementing all features of this endpoint will give customers the opportunity to view, change or delete personal information.

Flow

Privacy requests work as follows:
  • Request profiles for a specific customer.
  • After the request has been handled you will receive a callback containing the profiles that have been found and the personal information contained within them.
  • Present the data to the customer and/or provide a way to change data for each profile.
  • Delete or modify the profile when required.

Implementation

Step 1: Requesting profiles matching a cookie or e-mail address for a customer

Endpoint: /api/v1/privacy/requestPOST

Searching for profiles by e-mail:
{
	"callback_url": "https://example.com",
	"email": "example@example.com"
}

Searching for profiles by cookie:
{
	"callback_url": "https://example.com",
	"cookie": "<COOKIE_IDENTIFIER>"
}

Searching for profiles by email_hash (sha256 of the email):
{
	"callback_url": "https://example.com",
	"email_hash": "31c5543c1734d25c7206f5fd591525d0295bec6fe84ff82f946a34fe970a1e66"
}
API Response:
{
    "success": true,
    "callbackHash": "<CALLBACK_HASH>"
}

Step 2: Receiving the profiles on the specified callback URL

After processing the request the callback URL will receive a HTTP POST request with a JSON formatted string containing the profiles as payload.
{
    "callbackHash": "<CALLBACK_HASH>",
    "profiles": [
        {
            "profileHash": "<PROFILE_HASH>",
            "entities": {
                "12344": {
                    "firstname": "Fist",
                    "lastname": "Last",
                    "gender": "m",
                    "zipcode": "1234AB",
                    "city": "Amsterdam",
                    "country": "nl",
                    "phone": "+31612345678",
                    "email": "example@example.com",
                    "birthdate" => "1970-01-01",
                    "updated_at": "1970-01-01 01:00:00"
                }
            }
        }
    ]
}

Step 3: Changing fields in user profiles, or deleting them
Deleting a profile

Endpoint: /api/v1/privacy/request/{PROFILE_HASH}DELETE

{}
API Response:
{
    "success": true
}

Modifying a profile

Endpoint: /api/v1/privacy/request/{PROFILE_HASH}PATCH

{
	"entities": {
		"12345": {
            "firstname": "New first name",
            "lastname": "New last name",
            "gender": "f",
            "zipcode": "",
            "city": "",
            "country": "",
            "phone": "",
            "email": "example@example.com"
		}
	}
}
API Response when the request has been handled successfully:
{
    "success": true
}

API Response when the request has not been handled successfully:
{
    "success": false,
    "errors": {
        "INVALID_TEXT_FIELD_VALUE": {
            "entities": {
                "12345": {
                    "fields": {
                        "firstname": "Maximum length of 255 exceeded"
                    }
                }
            }
        },
        "INVALID_DATE_FIELD_VALUE": {
            "entities": {
                "12345": {
                    "fields": {
                        "custom_date_field": "Unrecognized date format"
                    }
                }
            }
        },
        "INVALID_NUMERIC_FIELD_VALUE": {
            "entities": {
                "12345": {
                    "fields": {
                        "custom_numeric_field": "Numeric value out of range (-99999.99999 to 99999.99999)"
                    }
                }
            }
        }
    }
}

Error codes for PATCH requests:
Error codes Description
NO_FIELDS_TO_UPDATE_SPECIFIED A profile was detected without any specified fields
INVALID_FIELDS_SPECIFIED One or more specified fields do not extist
INVALID_TEXT_FIELD_VALUE A textual string has a maximum size of 255 characters
INVALID_NUMERIC_FIELD_VALUE Numerical fields have a range and precision of -99999.99999 to 99999.99999
INVALID_DATE_FIELD_VALUE Dates should be specified in unix epoch timestamps or yyyy-mm-dd format


Response codes

HTTP status code Description Error codes
200 OK
202 Request was received, please wait for the callback
400
  • No identifier was included
  • More than one identifier included (email, cookie)
  • Callback URL missing
  • Callback URL does not use HTTPS SSL encryption
  • No entities in request found to modify
  • Modified data in entities did not validate (in this case the error property will contain an object with all found validation errors)
MISSING_IDENTIFIER
IDENTIFIER_AMBIGUOUS
MISSING_CALLBACK_URL
CALLBACK_URL_NOT_SECURE
NO_PROFILES_TO_MODIFY
404
  • Profile hash not included in the request
  • Profile hash invalid
MISSING_PROFILE_HASH
INVALID_PROFILE_HASH

Contacts

It is not needed to create new contacts.
When an event contains an email address, userid, or cookie we don't know or can't connect to an existing user, we will create a new contact.

If you want to add a contact to Squeezely, but there is no user activity like a PageView, send a CRMUpdate event through our backend(!) API.

Webhooks

You can use webhooks to get data or events from Squeezely to somewhere else.
For example, a webhook can be fired whenever someone unsubscribes from a newsletter list.
You can configure webhooks in the Squeezely interface.

Implementation examples on your webserver.

PHP
    // Example of parsing a application/x-form-urlencoded type webhook
    $data = $_POST;
    // Example of parsing a application/json type webhook
    $data = json_decode(file_get_contents('php://input'), true);
    // Example of parsing a GET request type webhook:
    parse_str($_SERVER['QUERY_STRING'], $data);
    // Squeezely will provide a signature for security
    $signature = $_SERVER['HTTP_X_SQUEEZELY_SIGNATURE'];

Security

We highly recommend to always verify the origin of received webhook callbacks.
Please read the documentation specific to verifying the origin of our webhooks.

Webhooks security

It is always a good idea to verify the origin of our webhook callbacks for security reasons.

Verification of provided signature

We send a signature along with every webhook call, contained in the HTTP request headers.
X-Squeezely-Signature: NzUxNzBmYzIzMGNkODhmMzJlNDc1ZmY0MDg3ZjgxZDk=

To validate this signature you need a private key, which you should handle like being a password. We use this key to generate a string, a base64 encoded binary representation HMAC hash.

Verifying the signature can be done as follows:
  1. Creating the formatted data:
    • Form URL encoded callback:
      • Take all received data, in order it was received.
      • JSON encode the data.
    • Callback with raw JSON body:
      • Take all data in the message body as a JSON encoded string.
  2. Create a binary representation of a HMAC hash by using the data from step 1, the `Webhook Key` using the SHA256 algorithm.
  3. Base64 encode the bytes obtained in the previous step.
  4. Compare the created hash with the hash obtained from the HTTP request headers. If they are equal the origin is confirmed.
Please note: It is advised to use method like hash_equals (php), secure_compare (ruby) or the solution available in your programming language of choice. These perform a `constant time` string comparison, which renders it safe from certain timing attacks. Regular plain equality operators do not prevent timing attacks.

Implementation examples

PHP
    /**
     * Verify a squeezely webhook signature
     *
     * @param string $secretKey The secret key
     * @param string $data Contains a JSON string of all data received in the webhook callback
     * @param string $signature The HMAC signature sent in the HTTP request header `X-Squeezely-Signature`
     *
     * @return bool Whether the message has been verified
     */
    function validSqueezelyWebhook(string $secretKey, string $data, string $signature): bool {
        if(version_compare(PHP_VERSION, "7.2.0") >= 0 && !in_array("sha256", hash_hmac_algos())) {
            throw new Exception("sha256 no longer supported");
        }

        $calculatedSignature = base64_encode(hash_hmac("sha256", $data, $secretKey, true));

        // Preventing timing attacks by using timing attack safe string comparison
        return hash_equals($signature, $calculatedSignature);
    }
    // Full usage example using an application/json formatted callback

    $signature = $_SERVER["HTTP_X_SQUEEZELY_SIGNATURE"];
    $rawData = file_get_contents("php://input");

    if(!validSqueezelyWebhook("SECRET_KEY", $data, $signature)) {
        // The message has not been validated
        exit;
    }

    // You can now use the contents of the callback
    $data = json_decode($rawData, true);

Products

Product feed

Setting your feed up is not a difficult process.
Make sure there is a feed available with products and categories. Categories are optional.
The feed can be in xml or json format and should look like this:

<?xml version="1.0" encoding="UTF-8"?>
<data>
    <products>
        <product>
            <name>Product X</name>
            <description>Product X description</description>
            <price>19.99</price>
            <currency>EUR</currency>
            <availability>in stock</availability>
            <image>http://www.yourstore.com/productx.jpg</image>
            <url>http://www.yourstore.com/productx</url>
            <inventory>24</inventory>
            <condition>new</condition>
            <brand>Brand Y</brand>
            <product_id>PR00019X</product_id>
            <category_ids>["1234","1235"]</category_ids>
            <parent_id>ABC123</parent_id>
        </product>
        ...
    </products>
    <categories>
        <category>
            <name>Category X</name>
            <description>Category X description</description>
            <url>http://www.yourstore.com/categoryx</url>
            <category_id>1234</category_id>
        </category>
        ...
    </categories>
</data>
    


Products property description:

property description
name Name of the product
description Description of the product
price Price in decimals (no thousand separator, dot for decimal separator). Example: 1345.50
currency Currency (EUR/USD/GBP)
availability in stock, out of stock or available for order
image URL of the main image of the product
url URL of the product
inventory Amount of products in stock
condition new or used
brand Brand of the product
product_id SKU or EAN you communicate with your customers. This needs to be unique.
category_ids Categories that have this product. JSON list of category ids.
parent_id Products with the same parent id will be grouped as variants in your feed


Category property description:

property description
name Name of the category
description Description of the category
url Url of the category
category_id SKU or your internal category id or reference. Mandatory Unique.

Feed documentation

Looking for the old version of the feed?
With a feed you can easily keep your product data in sync.
The feed should be formatted in either XML RSS 2.0 or ATOM 1.0 format. The Squeezely feed also supports Google Merchant Center Product Data feeds.

Supported properties


The following fields are supported in the feed.

property description
id The unique product ID (SKU or EAN) Mandatory
title Name of the product Mandatory
link URL of the product Mandatory
description Description of the product
price The price and currency of the product (EUR/USD/GBP). Price in decimals (no thousand separator, dot for decimal separator). Example: 1345.50 EUR
availability in stock (default), out of stock, available for order, preorder
image_link URL of the main image of the product. Minimal 600x600 pixels, preferably square.
image_links Supply up to 20 images for your product. (Overwrites image_link field).
List of <image_link> elements containing an url.
condition Condition of the product, new (default), used, refurbished.
inventory Amount of products in stock
brand Brand of the product
language 2-letter language code. (EN,DE,ES,FR,NL,NO,PL,TR,JP), contact for more. Default: EN.
parent_id Products with the same parent id will be grouped as variants in your catalog.
category_ids Categories that have this product. List of <category_id> elements containing an id.
google_product_category Include either numerical category ID (preferred) or the full path of the Google category.
Please refer to the Google Product Taxonomy documentation.
date_availability Availablity for travel, see more.
Array of all current product date availabilities (max 180 days), previously supplied availability will be erased.
[
    {
        "checkin" : "2019-09-23",
        "nights" : 7
    },
    {
        "checkin" : "2019-09-23",
        "nights" : 6
    },
]

Note on google_product_category
The Google Product Taxonomy Supports either numerical category identifiers, or a string containing the entire path of the category. Our platform needs to convert these to a consistent single format. For this we use the numerical category identifier.
It is important when using the full textual category paths to select the correct category path naming language. This way our platform can convert those to numerical ones. Currently Google supports the following unique languages:

Categories and Languages

A feed contains products of 1 language.
You can create your own categories, or you can use the google categories.

Supported properties for categories
property description
title Title of the category
description Description of the category
url Url of the category
category_id SKU or your internal category id or reference. Mandatory Unique
Below an example of an RSS feed enriched with custom categories

<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:g="http://base.google.com/ns/1.0" version="2.0">
    <channel>
        <title>Example - Online Store</title>
        <link rel="self" href="http://www.example.com"/>
        <updated>2011-07-11T12:00:00Z</updated>

        <item>
            <g:id>TV_123456</g:id>
            <g:title>LG 22LB4510 - 22" LED TV - 1080p (FullHD)</g:title>
            <g:link>http://www.example.com/electronics/tv/22LB4510.html</g:link>
            <g:image_link>http://images.example.com/TV_123456.png</g:image_link>
            <g:google_category_id>404</g:google_category_id>
        </item>
        <item>
            <g:id>TV_123456</g:id>
            <g:title>LG 22LB4512 - 24" LED TV - 1080p (FullHD)</g:title>
            <g:link>http://www.example.com/electronics/tv/22LB4512.html</g:link>
            <g:image_links>
                <g:image_link>http://images.example.com/CLO-1029384-1.jpg</g:image_link>
                <g:image_link>http://images.example.com/CLO-1029384-2.jpg</g:image_link>
            </g:image_links>
            <g:category_ids>
                <g:category_id>TV-1234</g:category_id>
                <g:category_id>TV-4321</g:category_id>
            </g:category_ids>
        </item>

        <category>
            <g:id>TV-1234</g:id>
            <g:title>TV's 22"</g:title>
            <g:description>Only the best TV's 22"</g:description>
            <g:link>http://www.example.com/tvs/22</g:link>
        </category>
        <category>
            <g:id>TV-4321</g:id>
            <g:title>TV's 24"</g:title>
        </category>
    </channel>
</rss>
Below an example of an RSS feed for travel including availability options

<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:g="http://base.google.com/ns/1.0" version="2.0">
    <channel>
        <title>Example - Online Hotel</title>
        <link rel="self" href="http://www.example.com"/>
        <updated>2011-07-11T12:00:00Z</updated>

        <item>
            <g:id>NL_ZH_DH_HOTEL_X</g:id>
            <g:title>Hotel The Hague</g:title>
            <g:link>http://www.example.com/nl/zh/hotel_the_hague.html</g:link>
            <g:image_link>http://images.example.com/HOTEL_X.png</g:image_link>
            <g:google_category_id>404</g:google_category_id>
            <g:date_availability>
                <g:availability>
                    <g:checkin>2019-09-11</g:checkin>
                    <g:nights>1</g:nights>
                    <g:price>1</g:price>
                </g:availability>
            </g:date_availability>
        </item>
        <category>
            <g:id>404</g:id>
            <g:title>Hotels</g:title>
        </category>
    </channel>
</rss>


Using Google categories
Language Identifier Google category list
Deutsch de-DE Open list
English (United Kingdom) en-GB Open list
English en-US Open list
español (Latinoamérica) es-ES Open list
français fr-FR Open list
Nederlands‎ nl-NL Open list
norsk no-NO Open list
polski pl-PL Open list
Türkçe tr-TR Open list
日本語 ja-JP Open list

More information on Google feeds
Please refer to the Google Merchant Center Product data specification documentation for more details about the specific feed specifications, and example files.

Validating feeds
The feed validator tool can help with creating and debugging compatible feeds. Please log in to make use of the feed validator.

Product availability

You can match a visitor's search timeframe with the availability of your products, hotel rooms, etc.
To do this we need to know which date(s) a visitor is searching for. Supply this info with the Search event (or any other event). See the documentation here:
Search event - documentation

We also need to know the availability of your products. You can supply dates and availability on those days for the upcoming 180 days.
You can find information on how to do this in the feed documentation:
Product feed - documentation

Now you can make a product set with the type Recommended for Travel. This dynamic product set will contain products that we recommend to the current visitor and that are available in the entire searched period.

DataLayer documentation

Squeezely can push data to the DataLayer for you.
If you are not familiar with DataLayer, please read this article.

Product Sets

Below an example of Product Set data we can push.
Note: You need to enable the "Expose to Datalayer" option in the Product Set.

    {
        'event': 'sqzl_productset',
        'product_set_id': 123,
        'product_set_data': [
            {
                'id': 'TV-123',
                'name': 'Tv 22 inch',
                'description': 'description',
                'image': 'http:..',
                'image_square': 'http:..',
                'url': 'http:..',
                'price': 1299.99
                'currency_sign': '$',
                'inventory': 24,
                'condition': 'new',
                'availability': 'in stock',
                'language': 'EN',
                'brand': 'Sony',
                'parent_id': 'TV',
            }
        ]
    }

Audiences

To get the audiences a visitor is currently in, please see the following DataLayer event.

    {
        'event': 'sqzl_customer_audiences',
        'audience': [
            199123,
            256623,
            ..
        ]
    }

Website Personalization

To get information about Website Personalization views or clicks, we provide the next data in the DataLayer.

Personalization view
This event is triggered when an variant (overlay/HTML insert) is triggered and displayed.
Note: The control_variant attribute is only provided when control group variant is triggered. Control groups don't see a variant, but this event is triggered for statistical purposes.
{
    'event': 'sqzl_PersonalizationView',
    'personalization_id': '123',
    'personalization_variant_id': '10', // or 'control' when it's a control group
    'control_variant': true // optional
}

Personalization click
This event is triggered when a visitor clicks on any link in the personalization variant.
{
    'event': 'sqzl_PersonalizationClick',
    'personalization_id': '123',
    'personalization_variant_id': '10',
}

If someone clicks on a product and the product information is available, additional product fields are added to the event.
{
    'event': 'sqzl_PersonalizationClick',
    'personalization_id': '123',
    'personalization_variant_id': '10',
    'product_id': '123',
    'product_title': 'Product title',
    'product_price': '112.00', // price, without currency sign
    'product_position': 3, // position of the product in the list,
}

Personalization documentation

The Squeezely Website Personalization will work immediately after installing the Frontend-tracking pixel.

Anti-flicker snippet

Sometimes you notice a page flicker when configuring a HTML insert. The reason is, our frontend-pixel is loaded later in your HTML code, hence the delay before the HTML is inserted.

We've built a small anti-flicker snippet which you must install as high as possible in the <head> of your website.
<script async type="text/javascript" src="https://squeezely.tech/p?hqs=1&m="></script>

It's advisable to not remove the async attribute, to avoid any page rendering issues in case of network problems.