This page lists all the events available in the module-data-analyticstracker.
For information on how to contribute new events, please see our Contributing Guide.
General recommendations, roles, and FAQs can be found on our Notion page.
Purpose: Identify the user.
When to use:
type Identify = {
id: string;
type?: 'administrator' | 'assessor' | 'author' | 'editor' | 'instructor' | 'learner' | 'manager' | 'support' | 'user';
user_wave?: string;
organisationId?: string;
cultureInfo?: string; // e.g. 'en-US'
isInternal?: boolean;
content?: {
packageId?: string;
packageTitle?: string;
method?: string;
methodId?: string;
edition?: string;
targetYear?: string;
businessUnit?: string;
productType?: string;
grade?: string;
schoolType?: string;
discipline?: string;
semanticVersion?: string;
};
};
tracker.identify({
id: 'my-user-id',
type: 'instructor',
user_wave: 'wave-1',
organisationId: 'my-guid',
cultureInfo: 'en-US',
isInternal: true,
content: {
packageId: 'pkg123',
packageTitle: 'Math 101',
method: 'online',
methodId: 'method123',
edition: '2nd',
targetYear: '2024',
businessUnit: 'education',
productType: 'course',
grade: '10',
schoolType: 'high-school',
discipline: 'mathematics',
semanticVersion: '1.0.0',
},
});
Purpose: Track when a user has loaded or navigated to a specific page.
IMPORTANT:
- Values for
typeandcategoryproperties must bekebab-case.- Before 1 Jan 2025, values for
typeandcategoryproperties should be documented on the pages below and approved by the Data Team:- After 1 Jan 2025, all product teams are encouraged to maintain their own lists of values without extra approval from the Data Team. This decision is related to shifting to a self-service mode for product analytics.
- If there is a request to the Data Team to build any logic on top of the tracking data (e.g. data science analysis, predictions), then product teams should align with the Data Team on property values and agree on a data contract. If sent properties are to be analyzed only in Mixpanel, then no alignment with the Data Team is needed.
type Page = {
category: string;
subCategory?: string;
type: string;
id?: string;
brand?: { name?: string };
pageName?: string;
metadata?: any;
};
type Referrer = {
module?: string;
label?: string;
itemId?: string;
elementId?: string;
};
tracker.page({
category: 'content',
subCategory: 'learning-content',
type: 'quiz',
id: 'my-quiz-id',
brand: { name: 'nectar' },
pageName: 'my-page-name'
});
If a referrer event is tracked right before the page event, referrer data will be added to the event.
tracker.referrer({
module: 'main-menu',
label: 'Do a quiz',
itemId: 'quiz',
});
For the referrer event, it is recommended to use attribute-based tracking.
<button title="Take me to the quiz" data-mdat="referrer" data-mdat-module="my-amazing-button"></button>
All custom events have the following base fields to specify where they occurred in the DOM:
type BaseFields = {
module?: string; // kebab-case, identifies the section of the page where the event occurred
itemId?: string; // kebab-case, identifies the item on which the event occurred
elementId?: string; // kebab-case, identifies the (HTML) element on which the event occurred
frameCorrelationId?: string; // kebab-case, identifies the frame in which the event occurred
};
When to use: When a user clicks on a link that leads outside of the current website.
Available actions: clicked
type ExitLink = {
url: string;
label?: string;
};
tracker.exitLinkClicked({
url: 'https://www.infinitaslearning.com',
label: 'Go to Infinitas',
module: 'main-menu',
itemId: 'infinitas-link',
});
When to use: When a user downloads, previews, or uploads a file.
Available actions: downloaded, previewed, uploaded
type FileDownloaded = {
name?: string;
id?: string;
source?: string;
extension?: string;
url?: string;
};
type FilePreviewed = {
name?: string;
id?: string;
source?: string;
};
type FileUploaded = {
name?: string;
id?: string;
source?: string;
extension?: string;
url?: string;
sizeMb?: number;
};
tracker.fileDownloaded({
url: 'https://www.infinitaslearning.com/report.pdf',
name: 'Answerbook',
id: '123abc',
source: 'edify',
extension: 'pdf',
});
When to use: When a user interacts with a form.
Available actions: submitted, clicked
The ProductEntity is defined in the e-commerce events documentation.
type FormSubmitted = {
name: string; // Name of the form
id: string; // The ID of the form.
product?: ProductEntity;
};
type FormClicked = {
name: string; // Name of the form
id: string; // The ID of the form.
clickText: string; // The label or text of the clickable element.
product?: ProductEntity;
};
tracker.formSubmitted({
id: 'form-66',
name: 'Zichtzending Getal & Ruimte JR',
});
When to use: Track interactions with frames on top of the page like pop-ups or widgets. Events that occur within the frame can be related to the frame by providing the frame-correlation-id.
Available actions: opened, closed, moved
opened: When a frame is opened. Consider using the page event instead if the frame covers the entire page. The frameOpened event generates a frame-correlation-id that can be used to correlate subsequent events within that frame.type Frame = {
type: string;
id?: string;
frameType: 'widget' | 'confirmation' | 'pop-up';
};
const frame = await tracker.frameOpened({
type: 'calculator',
id: 'home-page-calulator-widget',
frameType: 'widget',
});
closed: When a frame is closed.type ClosedFrame = Frame & {
result: 'confirmed' | 'rejected' | 'cancelled';
frameCorrelationId: string; // Required for this event
};
const closedFrame: ClosedFrame = {
...frame!, // Includes the frame-correlation-id
result: 'cancelled',
};
tracker.frameClosed(closedFrame);
moved: When a frame is moved.type MovedFrame = Frame & {
locationX?: number;
locationY?: number;
frameCorrelationId: string; // Required for this event
};
const movedFrame: MovedFrame = {
...frame!, // Includes the frame-correlation-id
locationX: 400,
locationY: 500,
};
tracker.frameMoved(movedFrame);
When to use: To track a list of items, often used for display or filtering/searching.
Available actions: displayed, filtered, ordered
displayed: When an item list is displayed, and filtering/searching is not applicable.type ItemList = {
type: string;
count?: number;
pageSize?: number;
pageNumber?: number;
displayMode?: string;
order?: {
field?: string;
direction?: 'asc' | 'desc';
};
};
tracker.itemListDisplayed({
type: 'books',
count: 58,
pageSize: 20,
pageNumber: 3,
displayMode: 'grid-view',
});
filtered: When an item list is searched or filtered.type FilteredItemList = ItemList & {
searchTerm?: string;
facets?: Record<string, (string | number | boolean | Date)[]>;
};
tracker.itemListFiltered({
type: 'books',
// ... other properties
facets: {
subject: ['english', 'biology'],
'target-year': ['1', '2'],
},
});
ordered: When an item list is reordered.type ItemListOrdered = ItemList & {
parentId?: string;
parentDescription?: string;
items: {
id: string;
description?: string;
sequence?: number;
}[];
};
tracker.itemListOrdered({
type: 'content-manage',
// ... other properties
});
When to use: Whenever there is no better semantic event available.
Available actions: clicked, loaded, blurred
clicked: When an element has been clicked.tracker.elementClicked({
elementId: 'example-checkbox',
type: 'checkbox',
value: 'true',
module: 'task-planner',
brand: { name: 'nectar' }, // optional
});
loaded: When an element has loaded.tracker.elementLoaded({
elementId: 'main-image',
type: 'image',
url: '/images/main.png',
});
blurred: When an element loses focus.tracker.elementBlur({
elementId: 'search-input',
type: 'text-input',
value: 'search term',
});
When to use: For A/B tests or other experiments.
Available actions: started
type Experiment = {
experimentName: string;
experimentGroup: 'control' | 'variant';
};
tracker.experimentStarted({
experimentName: 'my-experiment',
experimentGroup: 'control',
});
Every tracker call (page, identify, custom events, errorCapture) captures the page context (url, path, search, title, campaign) and the timestamp at the moment it is called. Sending can happen later (e.g. before Rudderstack is loaded or consent is given), but always uses this captured context, so a redirect right after tracking (e.g. a deeplink) doesn't move the event to the next page.
UTM parameters of the page the event is sent from are never added to the campaign of an event tracked on another page.
Events tracked before Rudderstack is loaded are kept in session storage when the page is reloaded or left in the same tab, and sent with their original page context and timestamp on the next page load. Events are lost only when the tab is closed before Rudderstack is loaded.
Call the tracker before navigating away. Data that is loaded after a redirect (await fetch(...) followed by tracker.page(...)) is captured on the new page.
If an event can only be tracked later, capture the page context when it happens and pass it to the tracker. This works for page, navigated and all custom events:
import { captureEventSnapshot } from '@infinitaslearning/module-data-analyticstracker';
const snapshot = captureEventSnapshot();
const data = await loadPageData();
tracker.page({ category: 'content', type: 'quiz', id: data.id }, { snapshot });
const clickSnapshot = captureEventSnapshot();
await saveTask();
tracker.elementClicked({ type: 'save' }, { snapshot: clickSnapshot });
Events tracked with data-mdat attributes (e.g., data-mdat="element-clicked") and automatically tracked links use the page context of the moment of the click, also when a click handler of the application navigates (e.g. a router link). The page context is captured before any other click handler runs.
The Data Team has introduced a flexible metadata property. If you need to send additional context that is not part of the core schema, the metadata property can be used.
tracker.elementClicked({
elementId: 'example-checkbox',
type: 'checkbox',
value: 'true',
module: 'task-planner',
itemId: 'add-content-unit',
metadata: JSON.stringify({ source: 'testbed', flag: 'alpha build', features: ['a', 'b', 'c'] }),
});
metadata allows you to include custom, event-specific properties.
These will be parsed into Mixpanel as metadata_<key> fields, enabling flexible analysis without compromising schema consistency.
Please be mindful when adding metadata. If usage becomes excessive, the Data Team may need to revise this approach.
Only add relevant metadata to the event, this is a test. If it get's out of hand, Data Team will need to move it to a separate event.