Skip to content

Metrilo/custom-integration

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

62 Commits
 
 
 
 
 
 

Repository files navigation

Metrilo custom integration

ℹ️ This guide is intended to be used by developers.

Metrilo helps you track the events that the people visiting your shop do - viewing specific pages or products, adding products to the cart, making orders, etc. The provided data is transformed into different reports and analytics metrics you could benefit from.

For more information about Metrilo and its features please visit the official website.

Overview

⚠️ We strongly recommend doing this on a Staging/Beta environment first to make sure the integration is smooth and nothing breaks down.

Quickstart guide

ℹ️ If you decide to follow along, you'll end up with some resources that you (most probably) won't use in the future. However, that's perfectly fine - after you're done testing, you can just ping us and we'll reset your project to a pristine state.

Once you've signed up for a Metrilo account, navigate to the Settings -> Installation page in your Metrilo project and keep your API Token and API Secret handy - you'll need them for the rest of this tutorial:

Now you need to import your shop's resources into Metrilo - categories, products, customers, orders. Then you can start registering actions on them - views, adds to cart, new orders.

Let's create a category, a product and a customer. We'll assume that:

  • the current time (in milliseconds since 1970) is 1518004715732
  • the API token of your Metrilo project is sh0p-t0k3n
  • the API secret of your Metrilo project is m3trilo-secr3t

ℹ️ Metrilo API uses a custom X-Digest header, which is an HMAC-SHA256 digest generated by using the request body string as the message and your Metrilo API secret as the key. You have to generate a separate digest for every resource call you make.

$ echo -n '{"time": 1518004715732, "token": "sh0p-t0k3n", "params": {"id": "1", "name": "Awesome clothing", "url": "https://my-awesome-shop.com/awesome-clothing"} }' | openssl dgst sha256 -hmac 'm3trilo-secr3t'
1ecd57653821936c3f5aceb1c20f49a815efdd70ef1f15e5902397aa83187550

$ curl -X POST "https://trk.mtrl.me/v2/category" -i -H "Content-Type: text/plain" -H "X-Digest: 1ecd57653821936c3f5aceb1c20f49a815efdd70ef1f15e5902397aa83187550" -d '{"time": 1518004715732, "token": "sh0p-t0k3n", "params": {"id": "1", "name": "Awesome clothing", "url": "https://my-awesome-shop.com/awesome-clothing"} }'
$ echo -n '{"time": 1518004715732, "token": "sh0p-t0k3n", "params": {"id": "2", "categories": ["1"], "price": 10.42, "name": "Awesome T-Shirt", "url": "https://my-awesome-shop.com/awesome-clothing/awesome-t-shirt"} }' | openssl dgst sha256 -hmac 'm3trilo-secr3t'
ee51936b99eb682989a9b89a50be0d50653b304af33c9ef03208c9e03d0d0745

$ curl -X POST "https://trk.mtrl.me/v2/product" -i -H "Content-Type: text/plain" -H "X-Digest: ee51936b99eb682989a9b89a50be0d50653b304af33c9ef03208c9e03d0d0745" -d '{"time": 1518004715732, "token": "sh0p-t0k3n", "params": {"id": "2", "categories": ["1"], "price": 10.42, "name": "Awesome T-Shirt", "url": "https://my-awesome-shop.com/awesome-clothing/awesome-t-shirt"} }'
$ echo -n '{"time": 1518004715732, "token": "sh0p-t0k3n", "params": {"email": "johnybravo@gmail.com", "createdAt": 1518004715732 } }' | openssl dgst sha256 -hmac 'm3trilo-secr3t'
621f776ad036ffb7c52caa053c75bc97d3024aeb85acc1c431b807a76b61d62f

$ curl -X POST "https://trk.mtrl.me/v2/customer" -i -H "Content-Type: text/plain" -H "X-Digest: 621f776ad036ffb7c52caa053c75bc97d3024aeb85acc1c431b807a76b61d62f" -d '{"time": 1518004715732, "token": "sh0p-t0k3n", "params": {"email": "johnybravo@gmail.com", "createdAt": 1518004715732 } }'

(We include the -i param so that you can verify a 200 status code for all these requests)

(For all available properties for those resources, see the managing resources section and the full API documentation)

The next step is to install the frontend library. Add the following snippet to your website (preferably the <head> tag):

<script type="text/javascript" src="https://trk.mtrl.me/tracking.js?token=sh0p-t0k3n"></script>

When you load that script, you should have access to a window.metrilo object. That's what you're going to use to create tracking events on behalf of your customers.

Now let's create a user journey, calling the necessary frontend functions each step of the way:

  • The customer johnybravo@gmail.com opens your homepage (but they are not logged in your website yet)
window.metrilo.viewPage('http://my-awesome-shop.com/', { name: 'Awesome homepage' }) // This would be called on your homepage
  • They navigate to the 'Awesome clothing' category (category ID and all other IDs are from the shop's database and should be passed as strings)
window.metrilo.viewCategory('1') // This would be called on the 'Awesome clothing' category page
  • They navigate to the 'Awesome T-shirt' product
window.metrilo.viewProduct('2') // This would be called on the 'Awesome T-Shirt' product page
  • They add one 'Awesome T-Shirt' to the cart
window.metrilo.addToCart('2', 1) // This would be called when a user clicks an add to cart button
  • They start checkout
window.metrilo.checkout() // This would be called whenever the customer starts the checkout process

At that point, all of the actions are done by an anonymous user. In order to associate them with a customer in Metrilo you will need to obtain their email - by asking them to login, from your order details form, or any other form. When you do - call the identify function with their email. After the idenfity call, all past and future actions will be attributed to this customer.

window.metrilo.identify('johnybravo@gmail.com') // This would be called whenever the customer provides their email address
  • They submit the order

When they submit the order, you'll need to send the order event from your backend:

$ echo -n '{"time": 1518004715732, "token": "sh0p-t0k3n", "params": {"id": "314", "createdAt": "1518004715732", "email": "johnybravo@gmail.com", "amount": "10.42", "status": "completed", "products": [{"productId": "2", "quantity": 1 } ] } }' | openssl dgst sha256 -hmac 'm3trilo-secr3t'
4401f8a26f2d2bf86df5354a8f7213464dd3da8368cf381af5494d518ba291c1

$ curl -X POST https://trk.mtrl.me/v2/order" -i -H "Content-Type: text/plain" -H "X-Digest: 4401f8a26f2d2bf86df5354a8f7213464dd3da8368cf381af5494d518ba291c1" -d '{"time": 1518004715732, "token": "sh0p-t0k3n", "params": {"id": "314", "createdAt": "1518004715732", "email": "johnybravo@gmail.com", "amount": "10.42", "status": "completed", "products": [{"productId": "2", "quantity": 1 } ] } }'

And that's it! Now when all events are processed by Metrilo, they will be attributed to the johnybravo@gmail.com user. You can check that out in the Customer Database tab in your Metrilo project.

ℹ️ Please allow for up to several minutes for all events to be processed.

ℹ️ If all backend calls return 200 and you're missing events - double check your input data.

API reference

Our API documentation is written according to the OpenAPI Specification. You can find all of the endpoints the Metrilo API serves and what parameters they require here.

ℹ️ The base url for each request is https://trk.mtrl.me/v2. Don't forget that you need to add your Metrilo API token as a token parameter in the request body.

If you have integrated with the previous version of our API, the guide has been moved here.

Creating and updating resources

A resource is a category, product, customer or order. Any time one of these changes on your backend, you should call the respective endpoint to create or update the resource in Metrilo. You can find more details for each endpoint in the documentation.

Endpoint Usage
/customer Create or update a single customer
/category Create or update a single category
/product Create or update a single product
/order Create or update a single order

All calls to these endpoints have to be done from your backend - therefore, we don't provide any specific code examples as the implementation is bound to your backend logic and programming language.

ℹ️ Each backend call except /customer must be sent with an additional custom header called X-Digest, which is an HMAC-SHA256 digest generated by using the request body string as the message and your Metrilo API secret as the key. This list provides great examples in different programming languages, which can help you with the implementation.

ℹ️ Each Metrilo project has its own API Token and multiple stores cannot point to the same Metrilo project.

ℹ️ Most of the time the data you send will override any existing data. For example, if you make a call about product A with categories C1 and C2 and then you make another call only with category C3, then the first two categories will be removed from the product. However, sometimes the data will be merged (e.g. adding a product's options). If the data is merged, it will be explicitly mentioned in the documentation.

ℹ️ Note that each request you send to Metrilo is limited to 5MB in size.

Tag / Untag customer

You can tag or untag existing Metrilo customers by calling the following endpoints from your backend.

Endpoint Usage
/customer/tag Adds tags to an existing customer (tags are merged, not overwritten)
/customer/untag Removes tags from an existing customer (missing tags are omitted)

Tag a customer

$ echo -n '{"time": 1518004715732, "token": "sh0p-t0k3n", "params": {"email": "test@metrilo.com", "tags": ["foo"]} }' | openssl dgst sha256 -hmac 'm3trilo-secr3t'
ac9600a205af6aea7be1a4a3f8044d80fb9f4fb84ce9b550265650beefb12e4a

curl -X POST "https://trk.mtrl.me/v2/customer/tag" -i -H "Content-Type: text/plain" -H "X-Digest: ac9600a205af6aea7be1a4a3f8044d80fb9f4fb84ce9b550265650beefb12e4a" -d '{"time": 1518004715732, "token": "sh0p-t0k3n", "params": {"email": "test@metrilo.com", "tags": ["foo"]} }'

Untag a customer

$ echo -n '{"time": 1518004715732, "token": "sh0p-t0k3n", "params": {"email": "test@metrilo.com", "tags": ["foo"]} }' | openssl dgst sha256 -hmac 'm3trilo-secr3t'
a2fc3d7dbe351311b433a1cf54edf59ef96885f0dcd1ede6e508a5ceb4c98a89

curl -X POST "https://trk.mtrl.me/v2/customer/untag" -i -H "Content-Type: text/plain" -H "X-Digest: a2fc3d7dbe351311b433a1cf54edf59ef96885f0dcd1ede6e508a5ceb4c98a89" -d '{"time": 1518004715732, "token": "sh0p-t0k3n", "params": {"email": "test@metrilo.com", "tags": ["foo"]} }'

ℹ️ The X-Digest header must be used here as well.

Importing resources

Before sending any tracking events to Metrilo, you need to import your data using the endpoints provided for each resource. Note that importing must be done in the order provided. You can find more details for each endpoint in the documentation.

# Resource Endpoint Required
1. Customers /customer/batch Yes
2. Categories /category/batch Yes
3. Deleted products /product/batch Only if you want to import orders for products that no longer exist in your database
4. Products /product/batch Yes
5. Orders /order/batch Only if you want to sync any historical data with Metrilo

⚠️ The order stated above is important, because orders are dependent on customers and products (which are in turn dependent on categories). An order won't be imported if Metrilo doesn't know about the customer or the product.

ℹ️ The X-Digest header must be used here as well.

Tracking library installation

Insert the following script tag in the page you want to track (we recommend inserting it in the <head> tag):

<script type="text/javascript" src="https://trk.mtrl.me/tracking.js?token=<YOUR_PROJECT_TOKEN>"></script>

Replace <YOUR_PROJECT_TOKEN> with the API token from within the Settings -> Installation page in your Metrilo project.

ℹ️ Make sure to remove the < and > symbols. So, for instance, if your token was 1234asdf, you would need to put in this snippet:

<script type="text/javascript" src="https://trk.mtrl.me/tracking.js?token=1234asdf"></script>

When you have successfully loaded the tracking library, you will have access to a window.metrilo object on your page.

ℹ️ You should add the script tag on every page that you want to track!

Tracking events

A tracking event is an action that a customer of yours does on your website - such as viewing a page, adding an item to their cart, ordering a product, etc. These actions are saved in the customer's current session and are the base of which Metrilo does its magic.

These are the functions you need to call on the window.metrilo object based on what a customer does on your website.

Whenever a customer you need to call
enters their email on your website identify
enters their details on your website customerDetails
visits a page viewPage
visits an article page viewArticle
visits a category page viewCategory
visits a product page viewProduct
types something in the search bar search
adds a product to their cart addToCart
removes a product from their cart removeFromCart
visits the checkout page checkout
does anything you'd like to tag applyTags
does anything customEvent

⚠️ It is extremely important not to cache any customer-action-specific calls. This will result in events being attributed to the wrong customer, which cannot be undone. If you are using full page caching, consider adding some sort of hole-punching mechanism.

ℹ️ Processing the calls to our API does not happen instantly - please allow for about a minute for them to be processed.

ℹ️ Keep in mind that if you try to send any tracking event for a resource that doesn't exist in Metrilo, your request won't be processed.

Identify

When a customer comes to the store and they are not logged in, Metrilo treats them as an anonymous customer by adding a unique identifier to their session (a cookie named cbuid), so that it could attribute their actions to this identifier. Once they provide an email (by logging in, signing up, filling in a subscription form, making an order, etc.) you need to call the identify function. This will associate the unique identifier with the email and all events that the customer had while being anonymous will be merged with the events they have as identified (if any).

It is enough to call identify only once - the first time the customer enters their email. If you are unsure whether you have already called it - just check the value of the cbuid cookie. If there is an email - no need to call it. Otherwise it will contain the unique identifier mentioned above.

ℹ️ Sometimes customers will log out, use different devices, browsers or delete their cookies. Every time that happens Metrilo will create a new anonymous customer with a new unique identifier. However, once the customer identifies themselves (enters their email and you call metrilo.identify) Metrilo will check for the existence of a customer with the entered email and if there is one, it will merge them with the anonymous customer.

  const email = 'johnnybravo@gmail.com' // Customer's email address

  window.metrilo.identify(email)

customerDetails

Customer has entered their details on a web form. This call updates the first name, last name and subscribed status of an existing customer.

  const params = {
    firstName: 'Johny', // Customer's first name (optional)
    lastName: 'Bravo', // Customer's last name (optional)
    phoneNumber: '+46 100 200', // Phone number (optional)
    subscribed: false // Subscribed status - true or false (optional)
  }

  window.metrilo.customerDetails(params)

viewPage

Customer has visited a page on your website. It can be the homepage, or any other page.

  const url = 'http://myshop.com/amazing-page' // Absolute URL to the visited page
  const params = {
    name: 'My Amazing page' // The name of the page in the shop
  }

  window.metrilo.viewPage(url, params)

viewArticle

Customer has visited an article page.

  const articleId = '42' // Unique ID of article resource in the shop's database
  const params = {
    name: 'How to increase sales' // Article display name in the shop
    url: 'http://myshop.com/how-to-increase-sales' // Landing page for the article resource
  }

  window.metrilo.viewArticle(articleId, params)

viewCategory

Customer has visited a category page.

  const categoryId = '9912' // Unique ID of category resource in the shop's database

  window.metrilo.viewCategory(categoryId)

viewProduct

Customer has visited a product page.

  const productId = '312' // The ID of the product in the shop's database

  window.metrilo.viewProduct(productId)

search

Customer has searched in the shop (this supports only a plain query string without further filtering).

  const query = 'a plant' // Search query string that the visitor entered in the search form
  const url = 'http://myshop.com/search/?s=a+plant' // The URL that the visitor landed on when submitting the search form

  window.metrilo.search(query, url)

addToCart

Customer has added a product to the cart.

  const productId = '312' // The ID of the added product
  const quantity = 2 // The quantity of added items

  window.metrilo.addToCart(productId, quantity)

removeFromCart

Customer has removed a product from the cart.

  const productId = '312' // The ID of the removed product
  const quantity = 1 // The quantity of removed items

  window.metrilo.removeFromCart(productId, quantity)

checkout

Customer has started the checkout process.

  window.metrilo.checkout()

applyTags

Adds tags to a customer.

  const tags = ['regular', 'big_spender'] // Tag labels that are assigned to the customer in the Metrilo application

  window.metrilo.applyTags(tags)

customEvent

Sends a custom event (anything you want to track).

  const customEventName = 'paypal_payment' // The name of the custom event

  window.metrilo.customEvent(customEventName)

Form integration

You can integrate a form (such as a newsletter subscription form) with Metrilo using the function below, that will also create all necessary Metrilo events for you when the form is submitted:

  window.metrilo.integrateForm({
    formSelector: '#newsletter-form', // required - a regular css selector for the form
    email: 'newsletter[fields][1]', // required - the name attribute of the "email" input field
    firstName: 'newsletter[fields][0][first]', // optional - the name attribute of the "first name" input field
    lastName: 'newsletter[fields][0][last]', // optional - the name attribute of the "last name" input field
    phoneNumber: 'newsletter[fields][3]', // optional - the name attribute of the "phone number" field
    subscribed: 'newsletter[fields][2][]', // optional - the name attribute of the "subscribed"  checkbox
    tags: ['newsletter-subscriber'], // optional - an array of tags to be applied
    customEvent: 'newsletter-subscribed' // optional - a custom event to be sent
  });

ℹ️ If you're loading the main Metrilo script asynchronously, you can use the window.metriloQueue object to defer functions until Metrilo is loaded. For example:

  (function() {
    const f = function () {
        window.metrilo.integrateForm({
          formSelector: '#newsletter-form',
          email: 'newsletter[fields][1]'
        });
    };
    if ((typeof window.metrilo !== 'undefined') && (typeof window.metrilo.integrateForm !== 'undefined')) {
      f();
    } else {
      window.metriloQueue = window.metriloQueue || [];
      window.metriloQueue.push(f);
    }
  })();

⚠️ If your form is not part of the DOM when the page is loaded (e.g. it appears after 30 seconds or whenever a user scrolls a certain amount), you would need to call that script after the form appears on the site so that the form is picked up.

Troubleshooting

Error codes

The following error codes are valid for all endpoints:

Code Message
200 Success response.
400 Bad request from client.
401 Project token is invalid.
402 Project requires payment.
403 The IP that the request came from is ignored.
500 Error from server while processing request.
502 Error from server accepting request.

For the backend endpoints, we have a couple of additional error codes:

Code Message
401 X-Digest header is not provided.
403 The provided X-Digest signature is invalid.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published