PageTracker
is the top level tracker. It is used to send page bound events like pageView
and instantiate other tracker objects that will be bound to one page, like StreamTracker
for tracking streams and RecommendationTracker
for recommendation panels.
Below is how to create a PageTracker
and send page view events tied to a certain page. It will need a PageContext
object that will list all of the properties that will be shared by all events sent from this page.
The values you fill in here should be discussed in the tagplan.
<html>
<head>
...
<script lang="text/javascript">
window.onload = function() {
...
// Create a PageTracker object, passing it the NPOTag and a PageContext object
const tracker = npotag.newPageTracker(tag, {
page: 'profile_page',
chapter_1: 'home',
chapter_2: 'profile',
// Scroll tracking can be enabled by setting it here to true
scroll_tracking: true,
// etc...
});
};
</script>
</head>
...
</html>
// Create a PageTracker object, passing it the NPOTag and a PageContext object
const tracker = newPageTracker(tag, {
page: 'profile_page',
chapter_1: 'home',
chapter_2: 'profile',
// Scroll tracking can be enabled by setting it here to true
scroll_tracking: true,
// etc...
});
// Create a context object with all property values
// All of the properties are optional
let context = PageContext(
page: "page",
chapter1: "chapter1",
chapter2: "chapter2",
chapter3: "chapter3",
broadcasters: "broadcasters",
program: "program",
contentContextId: "contextId",
queryContext: "queryContext",
condition: "condition",
errorCode: "errorCode",
customLabel1: "label1",
customLabel2: "label2",
customLabel3: "label3",
customLabel4: "label4",
customLabel5: "label5",
location: "location",
referrer: "referrer",
scrollTracking: true
)
// Instantiate the tracker object from the NPOTag shared instance
let tracker = NPOTag.shared.newPageTracker(with: context)
// Instantiate the tracker object from the NpoTag instance
val tracker = npoTag.pageTrackerBuilder()
.withPageName("home")
.withScrollTracking(true)
.withContentContextId("homeContextId")
.withCondition("condition")
.withQueryContext("query")
.withErrorCode("errorContext")
.withBroadcasters("broadcaster")
.withProgram("program")
.withChapters(
chapter1 = "C1",
chapter2 = "C2",
chapter3 = "C3"
)
.withCustomLabels(
customLabel1 = "L1",
customLabel2 = "L2",
customLabel3 = "L3",
customLabel4 = "L4",
customLabel5 = "L5"
)
.build()
Once created the tracker’s context is immutable, if you need to send events with new properties (because user has switched page for instance), you will need a new tracker instance with a different PageContext
.
The ways this SDK is intended to be used is that you should have one PageTracker
instance per page that is kept alive for the whole lifecycle of the page. Once a new page is reached, a new tracker should be instantiated.
See the contexts documentation for a detailed list of properties available for each context class.
Sends a pageView
event for the current page.
pageTracker.pageView();
pageTracker.pageView();
public func pageView()
pageTracker.pageView()
The NPOTag supports A/B testing by randomly assigning a given device or user into a test condition. (currently only available for Web). The same device/user will get the same condition across calls as long as the experiment name
and conditions
are not changed, so that one user will not see different pages when refreshing.
You can have an arbitrary number of A/B/C/… groups, but the weight
s should sum to 1.0. The method will return a string which corresponds to one of the condition name
fields OR default
when assignment failed (which you should handle correctly in your code).
Only events triggered after the abAssign()
call will contain the information about the A/B test. As such, you should generally keep this order of execution:
Because assignment is based on user information, abAssign should be called after logging in the user. In addition, because the measurements should contain the assigned field, so you must call abAssign
before the pageView. failure to keep the right order could influence A/B assignment validity and data collection
// login the user first (if this is a logged in user)
tag.login({
user_profile: 'example',
user_subscription: 'free',
user_pseudoid: 'example',
user_id: 'example',
});
const condition = pageTracker.abAssign({
experiment_name : 'button-test',
conditions: [
{ name: 'redButton', weight : 0.5},
{ name: 'greenButton', weight : 0.5},
]
});
// Example usage in your app
switch (condition) {
case 'redButton' : {
button.style.background = 'red';
break;
};
case 'greenButton': {
button.style.background = 'green';
break;
};
case 'default' : {
console.log('no match for AB condition')
button.style = ""
};
};
// Send the pageView after assignment
pageTracker.pageView();
// login the user first (if this is a logged in user)
tag.login({
user_profile: 'example',
user_subscription: 'free',
user_pseudoid: 'example',
user_id: 'example',
});
const condition = pageTracker.abAssign({
experiment_name : 'button-test',
conditions: [
{ name: 'redButton', weight : 0.5},
{ name: 'greenButton', weight : 0.5},
]
});
// Example usage in your app
switch (condition) {
case 'redButton' : {
button.style.background = 'red';
break;
};
case 'greenButton': {
button.style.background = 'green';
break;
};
case 'default' : {
console.log('no match for AB condition')
button.style = ""
};
};
// Send the pageView after assignment
pageTracker.pageView();
Users can interact with many things that are not links to content, such as a login button, a hamburger-menu foldout etcetera. The click event covers these cases.
There are for preset click types navigation
, action
, exit
and download
. These are the click events AT internet and Govolte support. Additionally the govolte plugin supports custom clicks types.
What name, type and chapters you fill in should be discussed in the tagplan.
pageTracker.click({
click_name: 'menu',
click_type: 'navigation' | 'action' | 'exit' | 'download' | string,
click_chapter_1: 'Home',
click_chapter_2: 'Navigation bar',
click_chapter_3: 'Left',
});
The type parameter can take any of the defined string values, or a custom string value. Parameters click_chapter_1/2/3
are optional:
pageTracker.click({
click_name: 'menu',
click_type: 'custom-click-type',
});
pageTracker.click({
click_name: 'menu',
click_type: 'navigation' | 'action' | 'exit' | 'download' | string,
click_chapter_1: 'Home',
click_chapter_2: 'Navigation bar',
click_chapter_3: 'Left',
});
The type parameter can take any of the defined string values, or a custom string value. Parameters click_chapter_1/2/3
are optional:
pageTracker.click({
click_name: 'menu',
click_type: 'custom-click-type',
});
pageTracker.click(
name: "menu",
type: ClickType.action,
chapter1: "Home",
chapter2: "Navigation bar",
chapter3: "Left"
)
The type parameter can take any predefined value exposed by the ClickType
enum, or a custom value using the .other
enum case. Parameters chapter1/2/3
are optional:
pageTracker.click(
name: "menu",
type: ClickType.other(value: "your_custom_type_here")
)
pageTracker.click(
name = "menu",
type = ClickType.Action(),
chapter1 = "Home",
chapter2 = "Navigation bar",
chapter3 = "Left"
)
The type parameter can take any predefined value exposed by the ClickType
sealed class, or a custom value using the .Other
class. Parameters chapter1/2/3
are optional:
pageTracker.click(
name = "menu",
type = ClickType.Other("your_custom_type_here"),
)
Click events with custom types are not supported by ATInternet so sending click events with such types will only be sent by the Govolte plugin, if it has been enabled.
This event can be used to track errors that occur on the page.
pageTracker.errorDisplayed({
error_message: "This is an error message",
});
pageTracker?.errorDisplayed({
error_message: "This is an error message",
});
pageTracker.errorDisplayed("error message")
pageTracker.error("error message")
Error events are not supported by ATInternet.
This function can be used to track the scroll position of the user on the page. It accepts any value between 0 and 100, inclusive. Make sure to call this function on a scroll event listener. It was designed to be called frequently.
Make sure to set the scrollTracking
property to true
when creating the PageTracker
object.
pageTracker?.scroll({ scroll_percentage: 25 });
pageTracker?.scroll({ scroll_percentage: 25 });
pageTracker.scroll(scrollPercentage: 25.0)
pageTracker.scroll(25)
Scroll events are not supported by ATInternet.
PageTracker can be used to track the time spent on a page.
In web SDK PageTracker
has a configuration flag heartbeat_enabled
which tracks the time spent on a page. When enabled, it automatically starts sending heartbeats without the need for any additional configuration.
npotag.newPageTracker(tag, { heartbeat_enabled: true });
newPageTracker(tag, { heartbeat_enabled: true })
The UIViewController subclass NPOTrackedViewController
provides an easy way of implementing the pageHearbeat event automatically.
Just inherit NPOTrackedViewController
and reference your correspondent pageTracker
, and the SDK will send the event every 10 seconds
class YourViewController: NPOTrackedViewController {
override var pageTracker: PageTracker {
viewModel.pageTracker
}
// ...
}
Alternatively you can always set up your own timer and frequencies, and use the PageTracker function sendPageHeartbeat()
to send the event.
pageTracker.sendPageHeartbeat()
PageTracker
provides a LifecycleObserver
that can be used to track the time spent on a page.
In your ViewModel, provide a getter for the LifecycleObserver
:
val lifecycleObserver: LifecycleObserver
get() = pageTracker.lifecycleObserver
The page (Activity, Fragment or Composable) that is being tracked should add the LifecycleObserver
to its lifecycle:
lifecycle.addObserver(viewModel.lifecycleObserver)
IMPORTANT: Make sure to remove the observer when the page is destroyed:
lifecycle.removeObserver(viewModel.lifecycleObserver)
Heartbeat events are not supported by ATInternet.