Snowplow Element Tracking Plugin

Browser Plugin to be used with @snowplow/browser-tracker.
This plugin allows tracking the addition/removal and visibility of page elements.
Maintainer quick start
Part of the Snowplow JavaScript Tracker monorepo.
Build with Node.js (18 - 20) and Rush.
Setup repository
npm install -g @microsoft/rush
git clone https://github.com/snowplow/snowplow-javascript-tracker.git
rush update
Package Installation
With npm:
npm install @snowplow/browser-plugin-element-tracking
Usage
Initialize your tracker with the SnowplowElementTrackingPlugin and then call startElementTracking:
import { newTracker } from '@snowplow/browser-tracker';
import { SnowplowElementTrackingPlugin, startElementTracking } from '@snowplow/browser-plugin-element-tracking';
newTracker('sp1', '{{collector_url}}', {
appId: 'my-app-id',
plugins: [ SnowplowElementTrackingPlugin() ],
});
startElementTracking({
elements: [
{selector: '.newsletter-signup'}
]
});
Configuration
Configuration occurs primarily via the elements setting passed to startElementTracking.
You can pass a single configuration or an array of multiple configurations.
Each configuration requires a selector, with a CSS selector describing the elements the configuration applies to.
All other configuration is optional.
You can label each configuration with the name property (if not specified, the selector is used as the name).
The name is used in the event payloads and matches the element_name of any entities specific to the target element(s).
The settings control triggering events for:
expose_element: When a selected element enters the viewport, becoming visible
obscure_element: When a selected element exists the viewport, no longer being visible
create_element: When a selected element is created or exists in the document
destroy_element: When a selected element is removed from or no longer found in the document
Each of these events can be enabled, disabled, or configured more specifically.
By default, only expose_element is enabled.
Rather than trigger events, configurations can also define the selected elements as "components", which can be listed as a component_parents entity for other events; or can have their current state attached to other events (such as page pings) via element_statistics entities.
The plugin manages the following custom entities:
element: This is shared between all the above events. It contains the element_name from the matching configuration, and data about the element that generated the event. This includes the element's dimensions, position (relative to the viewport and document), how many elements matched it's selector (and the index of the element in question, if you selector matches multiple elements). It will also contain custom attributes you can extract from the element via the details configuration.
component_parents: For the element generating the event, provides a list of components (defined by the component setting) that are ancestors of that element.
element_content: You can also attach details about child elements of the element that matches your selector. E.g. you can select a recommendations widget, and then extract details about the individual recommendations within it.
element_statistics: This entity can be attached to other events and provides a snapshot of what this plugin has observed at that point; it includes the current/smallest/largest dimensions so far, how long the element has existed since it was first observed, its current/maximum scroll depth, its total time in view, and how many times it has been visible in the viewport.
A detailed example configuration follows:
snowplow('startElementTracking', {
elements: [
{
selector: '.oncreate',
name: 'created div',
create: true,
destroy: true,
expose: true,
obscure: true,
details: [
function (element) {
return { example: 'from a function' };
},
{ attributes: ['class'], selector: true },
{ attributes: ['class'] },
{ properties: ['className'] },
{ dataset: ['example'] },
{ child_text: { heading: 'h2' } },
{ selector: true },
{ content: { textType: /text (\S+)/ } },
],
includeStats: ['page_ping'],
},
{ selector: 'nav', expose: false, component: true },
{
selector: 'div.toggled',
name: 'mutated div',
create: true,
destroy: true,
expose: false,
obscure: false,
},
{
selector: '.perpage.toggled',
name: 'perpage mutation',
create: { when: 'pageview' },
destroy: { when: 'pageview' },
expose: false,
obscure: false,
},
{
name: 'recommendations',
selector: '.recommendations',
expose: {
minTimeMillis: 5000,
minPercentage: 0,
minSize: 0,
boundaryPixels: 0,
},
obscure: true,
component: true,
details: { child_text: ['h2'] },
contents: [
{
name: 'recommendation-item',
selector: 'li',
details: { content: { item_name: /.+/ } },
contents: { name: 'recommendation_image', selector: 'img', details: { attributes: ['alt'] } },
},
],
},
{
name: 'shadow',
selector: 'button.shadow',
shadowSelector: 'shadow-host',
shadowOnly: true,
},
],
});
snowplow('getComponentListGenerator', function (componentGenerator, componentGeneratorWithDetail) {
snowplow('enableLinkClickTracking', { context: [componentGenerator] });
snowplow('enableFormTracking', { context: [componentGenerator] });
});
snowplow('endElementTracking', {elements: ['names']});
snowplow('endElementTracking', {elementIds: ['id']});
snowplow('endElementTracking', {filter: (config) => true});
snowplow('endElementTracking');
Copyright and license
Licensed and distributed under the BSD 3-Clause License (An OSI Approved License).
Copyright (c) 2024 Snowplow Analytics Ltd.
All rights reserved.