Page Tracker

PageTracker

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.

pageView

Sends a pageView event for the current page.

pageTracker.pageView();
pageTracker.pageView();
public func pageView()
pageTracker.pageView()

abAssign

⚠️ (experimental feature, web-only) ⚠️

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 weights 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:

  1. Create the tag
  2. Create the PageTracker
  3. Login (if applicable)
  4. abAssign()
  5. PageView()
  6. OtherEvent

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();

click

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.

Error

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.

Scroll

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.

Page Heartbeat

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.