Analytics
For publishers who implement some components via API, you'll have to set up event handling to access Tipser analytics. This enables the same tracking functionality as our elements already support. If your site includes a mix of elements and custom/API components, handling API events will help you understand the shopper's behavior throughout their shopping experience.
Connect to Tipser analytics
You can connect to Tipser analytics by listening to the tw-track
event on your page:
<script>
const analyticsHandler = function (e) {
//put here your own code handling the event, example below
const detail = e.detail;
console.log('Tipser analytics event: ', e);
console.log('Action',detail.action); //e.g. 'Cart'
console.log('Target',detail.target); //e.g. 'Product'
console.log('Description',detail.description); //e.g. 'Product added to cart'
console.log('Object',detail.object); //payload of the event (e.g. product id, price, etc)
}
document.addEventListener('tw-track', analyticsHandler);
</script>
Example events intercepted this way are:
- the user viewed a product on your page
- a product was added to cart
- product checkout dialog was opened
- transaction was finalized
For complete list of supported events refer to the Supported events section.
What you do with those events is up to you. Typical usage examples are:
- forwarding them to your analytics system (e.g. Google Analytics, as described here)
- logging them to the browser console for easier debugging
Events structure
Each event passed to analyticsHandler
function follows the following structure:
{
detail: {
action: string, # what action is taken on the target, mandatory
target: string, # where this action is taken, mandatory
description: string, # describing what is being logged
object: # details about the tracked object, e.g. product name, product price, etc.
[
{
# some properties here
},
..., # this array can contain more than 1 object
]
}
}
As you can see, all the useful data is contained in the top-level detail
field of the event object.
Typical use case: Google Analytics
In case you want to forward Tipser Analytics events to your Google Analytics, you can use this code snippet:
document.addEventListener('tw-track', function(e) {
// ga() function coming from analytics.js library
ga('send', {
hitType: 'event',
eventCategory: e.detail.description,
eventAction: e.detail.action,
eventLabel: e.detail.target,
});
});
The code above assumes that you use analytics.js GA client library on your page. For other libraries, like gtag.js, that code needs to be slightly adjusted.
For the instructions how to setup analytics.js script on your site and connect it to your GA account, refer to the official documentation.
The above example is just a very trivial example of integrating Tipser events with GA. For a more thorough implementation involving Enhanced Ecommerce extension, please refer to this gist.
For example, if you're using analytics.js script to integrate with Google Analytics, you need to add the line below (as described here) at the end of the snippet copied from your GA account:
ga('require', 'ec');
and make sure that Enhanced Ecommerce extension is enabled in your GA settings:

Typical use case: Facebook Pixel
In case you want to forward Tipser Analytics events to your Facebook Pixel account, you can use the following code snippet:
document.addEventListener('tw-track', function(e) {
// fbq() function coming from Facebook Pixel analytics script
fbq('trackCustom', e.detail.action, {
content_name: e.detail.target,
content_category: e.detail.description,
content_type: e.detail.action,
});
});
The example above doesn't translate Tipser events to standard Pixel events, you will have to make a correlation in the Pixel dashboard or you can write a custom mapping function.
-
Expand and copy the snippet script.
-
Paste it above
addEventListener
for tw-track event. -
Use it the same way as in the example below
Snippet
```javascript const callPixelEvent = function(e) { const action = e.detail.action; const target = e.detail.target; const object = e.detail.object; switch (true) { case action === 'Click' && target === 'Product tile': { const product = object[0]; fbq('track', 'ViewContent', { currency: (product.salesPrice || product.listPrice || product.priceIncVat).currency, value: (product.salesPrice || product.listPrice || product.priceIncVat).value, content_name: product.name || product.title, content_ids: [product.id], }); break; } case action === 'Cart' && target === 'Product': { const product = object[0]; if ((product.name || product.title) && (product.salesPrice || product.listPrice || product.priceIncVat)) { fbq('track', 'AddToCart', { currency: (product.salesPrice || product.listPrice || product.priceIncVat).currency, value: (product.salesPrice || product.listPrice || product.priceIncVat).value, content_name: product.name || product.title, content_ids: [product.id], }); } else { fbq('track', 'AddToCart', { content_ids: [product.id], }); } break; } case action === 'Cart' && target === 'Payment': { const products = object; fbq('track', 'InitiateCheckout', { content_ids: products.map((p) => p.id), contents: products.map((p) => p.name).join(', '), currency: (products[0].salesPrice || products[0].listPrice || products[0].priceIncVat).currency, num_items: products.reduce((totalQuantity, product) => product.quantity + totalQuantity, 0), value: products.reduce((totalPrice, product) => product.quantity * (product.salesPrice || product.listPrice).value + totalPrice, 0), }); break; } case action === 'Purchase' && target === 'Order': { const products = object.map((order) => order.Products).flat(); fbq('track', 'Purchase', { value: products.reduce( (totalPrice, product) => totalPrice + (product.salesPrice || product.listPrice || product.priceIncVat).value, 0 ), currency: (products[0].salesPrice || products[0].listPrice || products[0].priceIncVat).currency, content_ids: products.map((product) => product.id), contents: products, content_type: 'product', }); break; } default: break; } };
</p>
</details>
```javascript
document.addEventListener('tw-track', callPixelEvent);
The code above assumes that you use pixel.js facebook client library on your page.
For the instructions how to setup pixel.js script on your site and connect it to your Facebook for Developers account, refer to the official documentation.
Supported events
View events
View cart-tab
A cart tab component was rendered on the page visited by the user (we don’t really check if it’s in the viewport)
detail
object structure
{
description: ‘View cart-tab',
action: 'View',
target: 'Cart-tab',
object: [],
posId: string,
referrer: string,
url: string
}
View cart
The user is presented with the cart phase.
detail
object structure
{
description: 'View Cart'
action: 'View'
target: 'Cart'
object: OrderedProductLegacy[],
posId: string,
referrer: string,
url: string
}
Quick links to object structures: OrderedProductLegacy
View collection
When a collection component (or a part of it) appears in the viewport of the user's browser.
detail
object structure
{
description: ‘Collection viewed’,
action: 'View',
target: 'Collection',
object: {
id: string,
items: {
product: Product
}[]
}[],
posId: string,
referrer: string,
url: string
}
Quick links to object structures: Product
View product details
It is emitted every time product detail page was viewed by the user (as a modal or as an embedded product page). In the current implementation it’s always sent together with the click event (can be changed upon request)
detail
object structure
{
description: 'Product detail page viewed',
action: 'View',
target: 'Product',
object: Product[], # Product which interests us is the first element of an Array
posId: string,
referrer: string,
url: string
}
Quick links to object structures: Product
View product tile
A product tile component was in the viewport of the user's browser. If it disappears and reappears in the viewport, this generates another instance of the event.
detail
object structure
{
description: 'View product tile'
action: 'View'
target: 'Product tile'
object: Product[],
posId: string,
referrer: string,
url: string
}
Quick links to object structures: Product
View shop
A store component (or part of it) was in the viewport of the user’s browser.
detail
object structure
{
description: 'Shop viewed',
action: 'View',
target: 'Shop',
object: {
id: string, # collection id
items: Product[], # products
url_slug: string # store url slug
}[],
posId: string,
referrer: string,
url: string
}
When a category is changed in the store, this event will be sent again with a different set of products and collection id.
Click events
Click payment button
User has clicked the payment button.
detail
object structure
{
description: 'Click payment button'
action: 'Click'
target: 'Payment button'
object: { # Describes how the user is paying and where they clicked the button
from: string, # Possible values are
# `Checkout`, `Cart`
paymentMethod: string, # Possible values are
# `APPLE`, `BROWSER`, `GOOGLE`, `KlarnaRest`, `PayPal`, `StripePaymentIntents`
}[],
posId: string,
referrer: string,
url: string
}
Click product
When a product tile component is clicked by the user (either a standalone product tile or from a collection).
detail
object structure
{
description: 'Product tile clicked',
action: 'Click',
target: 'Product tile',
object: Product[],
posId: string,
referrer: string,
url: string
}
Quick links to object structures: Product
Cart events
Add product to cart
A product was added to cart or the quantity of the product in the cart was increased (increasing a quantity by X will always generate only one “add to cart” event but with a proper quantity parameter).
detail
object structure
{
description: ‘Product added to cart’,
action: 'Cart',
target: 'Product',
object: ProductLegacy[],
posId: string,
referrer: string,
url: string
}
Quick links to object structures: ProductLegacy
Remove product from cart
A product was removed from the cart or the quantity of the product in the cart was decreased (decreasing a quantity by X will always generate only one "remove from cart” event but with a proper quantity parameter).
detail
object structure
{
description: ‘Product removed from cart’,
action: 'Cart',
target: 'Product',
object: ProductLegacy[],
posId: string,
referrer: string,
url: string
}
Quick links to object structures: ProductLegacy
View cart with intent to check out
The user opened the checkout view (every time the user enters this view or refreshes this page will generate another instance of the event)
detail
object structure
{
description: 'View cart - payment in viewport',
action: 'View',
target: 'Payment',
object: OrderedProductLegacy[],
posId: string,
referrer: string,
url: string
}
Quick links to object structures: OrderedProductLegacy
Purchase events
Product purchased
When a product was bought (thank you page).
detail
object structure
{
description: ‘Product purchased’,
action: 'Purchase',
target: 'Order',
object: { # Describes the order, the purchased items, and how the user completed their purchase
OrderId: string,
Products: ProductLegacy[]
from: string, # Possible values are
# `Checkout`, `Cart`
paymentMethod: string, # Possible values are
# `APPLE`, `BROWSER`, `GOOGLE`, `KlarnaRest`, `PayPal`, `StripePaymentIntents`
}[],
posId: string,
referrer: string,
url: string
}
Quick links to object structures: ProductLegacy
Objects structures
Categories
structure
Categories
structure department: string,
section: string,
productType: string
Image
structure
Image
structure{
[key]: string
id: string,
original: string
}
Each value is url for the certain variation of an image. key
determines size, and it is one of following: 250x
, 450x
, 960x
, 50x50
.
Price
structure
Price
structure{
value: number,
currency: string, #ISO 4217
formatted: string, # human readable price string
}
Product
structure
Product
structure{
id: string,
title: string,
images: Image[],
brand: string,
catgories: Categories
currency: string, #ISO 4217
description: string,
priceInVat: Price,
isInStock: boolean,
variants: [],
vat: { # percentage of VAT
value: number,
formatted: string, # human readable value percentage string
}
categoriesValue: string
}
Quick links to object structures: Categories, Price, Image
Legacy object structures
These objects are replaced by newer versions, but may still be encountered in the system.
CategoriesLegacy
structure
CategoriesLegacy
structure{
[key]: string
}[]
OrderedProductLegacy
structure
OrderedProductLegacy
structure{ # Representation of product, but slightly different schema than Product
id: string,
name: string,
brand: string,
campaign: undefined,
categories: CategoriesLegacy
merchant: string
image: string, # url
listPrice: Price,
salesPrice: Price,
variant: [],
posId: string,
quantity: number
}
Quick links to object structures: CategoriesLegacy, Price
ProductLegacy
structure
ProductLegacy
structure{ # Representation of product, but slightly different schema than Product
id: string,
name: string,
brand: string,
campaign: undefined,
categories: CategoriesLegacy
image: string, # url
listPrice: Price,
salesPrice: Price,
deliveryCost: Price,
variant: [],
merchant: string
}
Quick links to object structures: CategoriesLegacy, Price
Disabling analytics
In case analytics needs to be disabled (e.g. as a result of the user rejecting the GDPR terms), the disableAnalytics: true
configuration option can be used. Doing so will prevent the following from happening:
- sending web requests to Tipser's Google Analytics property
- sending web requests to Tipser's internal analytics system (stats.tipser.com)
- placing Google Analytics tracking cookies in the user's browser by Tipser's Google Analytics script
Disabling analytics statically vs dynamically
You can decide to disable analytics from the start when disableAnalytics: true
setting is a part of your initial configuration.
Or, instead, you may want to initially keep it enabled (by setting disableAnalytics: false
setting in your initial configuration or simply skipping that setting) and only disable it dynamically at the later time by updating the value of disableAnalytics
config to true
(e.g. at the moment when the user declines the GDPR terms).
You can dynamically update disableAnalytics
value with the following line:
tipserScript.updateConfig({disableAnalytics: true});
The configuration setting
disableAnalytics: true
does not blocktw-track
events from being emitted. In case you are translatingtw-track
events to analytics events (e.g. as described in Typical use case: Google Analytics section), then it's your responsibility
to block that sending your own analytics events when necessary.
Updated about 1 year ago