Analytics
You can connect to Tipser analytics by implementing the onAnalyticsEvent
event handler on your page:
const tipserElementsConfig = {
eventsHandlers: {
onAnalyticsEvent: (e) => {
const {detail} = e;
//Logging out some useful stuff
console.log('Tipser analytics event: ', e);
console.log('Action',detail.action);
console.log('Target',detail.target);
console.log('Description',detail.description);
console.log('Object',detail.object);
//Your custom mapping function goes here
const internalEvent = transformTipserEventToInternalEvent(e);
//Pushing analytics event to the analytics system of your choice (GA, FB Pixel, in-house analytics)
fireInternalAnalyticsEvent(internalEvent);
}
}
...
}
...
<TipserElementsProvider config={tipserElementsConfig}>
...
</TipserElementsProvider>
Example events intercepted this way are:
- the user viewed a product on your page
- a product was added to cart
- the checkout view was presented to the user
- a transaction was completed
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 to debug your integration with Tipser Elements
Typically, some conditional logic may be needed to filter out specific types of events. E.g. to only push PayPal transactions events to your analytics, you can implement the following check:
onAnalyticsEvent: (e) => {
const {detail} = e;
//Filtering out PayPal transactions
if(detail.action === 'Purchase' && detail.target === 'Order' && detail.object[0].paymentMethod ===
'PayPal') {
const {Products, OrderId} = detail.object[0]
const internalEvent = createInternalPayPalTransactionEvent(Products, OrderId);
fireInternalPayPalPaymentEvent(internalEvent);
}
}
Events structure
Each event passed to tipserEventsCallback
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 you 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
The user is presented with the cart phase.
detail
object structure
{
description: 'View Cart'
action: 'View'
target: 'Cart'
object: []
}
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: []
}
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,
ownerUserId: string,
created: string, #e.g. DateTime ISO 2019-06-11T08:40:29.377Z
modified: string, #e.g. DateTime ISO 2019-06-11T08:40:29.377Z
postComment: null | ?
product: Product[]
}
}
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
}
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[]
}
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
}
]
}
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`
}
]
}
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[]
}
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[]
}
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[]
}
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[]
}
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`
}
]
}
Quick links to object structures: ProductLegacy
Data policy events
Consent to data policy
User has accepted the data policy.
detail
object structure
{
description: 'Accepted data policy'
action: 'Consent'
target: 'Data policy'
object: []
}
Reject data policy
User rejected the data policy.
detail
object structure
{
description: 'Rejected data policy'
action: 'Reject'
target: 'Data policy'
object: []
}
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,
variant: [],
merchant: undefined
}
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).
To change the analytics settings, just update the value passed to the config
prop of TipserElementsProvider
in the next render cycle:
const elementsConfigWithAnalytics = {...baseElementsConfig, disableAnalytics: shouldDisableAnalytics()};
return <TipserElementsProvider config={elementsConfigWithAnalytics}>
...
</TipserElementsProvider>
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 over 1 year ago