Skip to content

Dynamic Tracking: Setup and configuration

The standard Parse.ly tracking code is useful for most situations. However, there are times when you want more control over the behavior of this code. Perhaps you don’t want the code to trigger a pageview automatically. Or, you may want to trigger multiple page views, at different times, on the same page (not to be confused with single-page applications). In these cases, we recommend that you implement Dynamic Tracking:

  • Infinite scroll
  • Image carousels
  • Sending custom events
  • Tracking downloadable files

Overview

Here is a full example that we will then break into functional parts:

<script>
  window.PARSELY = window.PARSELY || {
    onload: function() {
      // will be called once PARSELY tracking code is loaded

      // bind pageview tracking for all "next" links.
      // example event listener; set your own based
      // on your site design
      jQuery("a.next").on("click", function() {
        var url = this.href,
          urlref = location.href;

        PARSELY.beacon.trackPageView({
          url: url,
          urlref: urlref,
          js: 1
        });
        return true;
      });
    }
  };
</script>

<!-- START Parse.ly Include -->
<!-- ...insert the parsely tracker code here... -->
<!-- END Parse.ly Include -->

Note

The dynamic tracking code must be placed before the standard Parsely tracking snippet.

The code above waits until the Parse.ly tracking code has finished loading, and then using jQuery attaches to all click events for links with class next. On click, a request to the analytics server is sent. The url of the tracking event is set to the link that was clicked, whereas the urlref is set to the current URL (before the event is sent and before a page transition happens).

This preserves the “internal referrer” (page-to-page tracking) for Parse.ly, while still allowing you to load the next piece of content dynamically, without incurring the cost of a full page refresh.

Note that url and urlref values are required to be absolute paths. This means that relative paths are not accepted (e.g. "/article" as opposed to "http://www.example.com/article"); they must be full URLs. They should also resolve or redirect to an actual page on your site that has crawlable metadata (see Providing Metadata for Dynamic Content below).

The onload handler

Parse.ly’s tracker code loads asynchronously, so the only way to reliably interact with its API is to set a handler for an onload event that the API exposes.

Define a PARSELY object before the tracking code like this:

<script>
  window.PARSELY = window.PARSELY || {
    onload: function() {
      console.log("Parse.ly code has loaded");
      // add your event listeners here
    }
  };
</script>

<!-- START Parse.ly Include -->
<!-- ...insert the parse.ly tracker code here... -->
<!-- END Parse.ly Include -->

Adding an event listener

Find the appropriate selector and attach an event listener to use as the trigger for when to send the dynamic tracking call. You can use jQuery (as in the example below) or vanilla JavaScript with an addEventListener() method.

The below example imagines a site that has an <a> tag with a class value of next (<a class="next" href="...">) that will trigger when it is clicked. Your event listener will be different.

jQuery("a.next").on("click", function() {
  var url = this.href,
  urlref = location.href;

  //dynamically send tracking call

  return true;
});

Dynamically sending a tracking call

To send a tracking request to the analytics server use PARSELY.beacon.trackPageView. It takes a single JavaScript object (dictionary) with keys and values that will be beaconed to Parse.ly’s servers.

Note that the function is available only after the tracker code has finished loading.

PARSELY.beacon.trackPageView({
  url: url,      // URL to be tracked
  urlref: urlref,   // Referring URL
  js: 1        // flag indicating this is dynamic
});

We used this object to demonstrate how to Track Files.

Disabling on-load tracking

The default behavior of the tracking code is to report an event as soon as the script has finished loading. You can prevent the behavior, by setting PARSELY.autotrack to false before the include.

<script>
  window.PARSELY = window.PARSELY || {
    autotrack: false,
    onload: function() {
      // add event listeners or other dynamic tracking logic, such as:
      // PARSELY.beacon.trackPageView({ ... })
    }
  };
</script>
<!-- START Parse.ly Include -->
<!-- ... as above ... -->
<!-- END Parse.ly Include -->

Subsequent events could then be tracked using dynamic tracking.

If your account supports engaged time tracking, heartbeat events will be sent on every page by default, even when PARSELY.autotrack is set to false. If you plan to use dynamic tracking for pageview events, this behavior ensures that the tracker captures the full engagement. But if you need to disable both pageviews and heartbeat events, additionally set PARSELY.config.heartbeat_should_honor_autotrack to true, as in the example below.

<script>
  window.PARSELY = window.PARSELY || {
    autotrack: false,
    config: {
      heartbeat_should_honor_autotrack: true
    },
    onload: function() {
      // add event listeners or other dynamic tracking logic, such as:
      // PARSELY.beacon.trackPageView({ ... })
    }
  };
</script>
<!-- START Parse.ly Include -->
<!-- ... as above ... -->
<!-- END Parse.ly Include -->

This option is only supported in tracker versions above 1.0.3. If you’re unsure of your tracker version, contact support@parsely.com

Providing Metadata for Dynamic Content

While you can fire pageviews dynamically, Parse.ly’s web crawler, which extracts your metadata, can’t execute JavaScript. It must be able to access the metadata tag from the results of a single GET request. That means your metadata has to be included directly in the page source.

To configure metadata for dynamic content, just make sure that any content loaded dynamically can also be accessed at a standalone, static URL. For example, perhaps you have an article http://example.com/article1, and when a reader reaches the bottom of the page, you load a new article via infinite scroll, firing a pageview for http://example.com/article2. Parse.ly’s crawler can pick up that new article’s metadata just fine, provided that http://example.com/article2 is publicly accessible, with the desired metadata included in the page source.

This also means that any URLs sent as part of a dynamic tracking call should resolve to a page on your site that hosts metadata as described above. In the case of a photo gallery that loads with qsargs, hash URLs, Javascript, or scroll, you can use a dedicated qsarg in the URL that’s sent to Parse.ly (example: a photo gallery that takes place on example.com/base would have /base?slide=1/base?slide=2, etc.). The key here is to ensure that the canonical URL is always the same as it will be our source for the metadata on the page.

Sending custom events

Parse.ly instruments pageview events by default. This helps us track views and visitors. We also instrument heartbeat events for customers who have accounts with support for engaged time.

In addition, our video tracker instruments two events, videostart and vheartbeat. The former tracks video start events and video visitors, while the latter tracks engaged time while watching videos.

However, you can send other custom events to Parse.ly by changing the action attribute in your dynamic tracking calls.

To guarantee you don’t use a Parse.ly reserved name, we recommend you prefix custom events with an underscore, e.g. _subscribe to track an e-mail newsletter subscription event, or _share to track a share button click event. Here is an example of tracking a custom social share event from your pages:

PARSELY.beacon.trackPageView({
  url: url,
  urlref: urlref,
  action: "_share"    // custom event type
});

These custom events will be ignored by Parse.ly’s dashboard and live APIs, but will be accessible to you via Parse.ly’s Raw Data Pipeline.

Sending custom data with events

Arbitrary data can be included in the trackPageView call by including a data attribute in the argument object. This could be used to track a custom per-page or per-user data, such as identifiers or internal web application data.

Note that the data object cannot include the keys parsely_uuid or parsely_site_uuid. Again, we recommend you use a leading underscore to avoid collision with reserved Parse.ly names. So, for example, to track a custom “scroll” event that also includes the current scroll depth, you could send the following:

PARSELY.beacon.trackPageView({
  url: url,
  urlref: urlref,
  action: "_scroll",   // custom event type
  data: {
    _y: window.scrollY // custom event attribute
  }
});

Again, this custom scroll event will be ignored by Parse.ly’s dashboard and APIs, but you can use it to do scroll depth calculations via Parse.ly’s Raw Data Pipeline. In that case, it would show up as events where action is _scroll and extra_data._y is set to an integer in the JSON object of your raw records.

When debugging custom events, you can filter on that action name in the network tab of your browser development tools: _scroll for the event above.

You can also use updateDefaults to set persistent custom data that will be sent along with each event regardless of whether you’re using dynamic tracking.

window.PARSELY = window.PARSELY || {
  onload: function() {
    PARSELY.updateDefaults({data: {_y: window.scrollY}});
  }
};

Calling updateDefaults in onload will cause the passed parameters to be sent with all pixel requests from the tracker, including the initial pageload, video and engagement events, and and dynamic tracking calls. Any default data properties set this way can still be overridden in a PARSELY.beacon() call. As above, fields nested in a data object will appear in the Raw Data Pipeline as attributes on extra_data.

Queueing events before onload

When loading the Parse.ly JavaScript tracker asynchronously (the default behavior), it is possible that you’ll want to track events before the tracker has finished loading. This situation can arise when using an infinite-scroll layout, for example.

To handle this situation, you can queue events that occur before PARSELY.onload is called and flush that queue during onload. The following example code demonstrates this technique.

var parselyPreload = {eventQueue: [], loaded: false};

// run this when you would fire an event
function fireParselyEvent() {
  var event = {
    url: location.href,
    urlref: document.referrer,
    js: 1
  };
  if (parselyPreload.loaded) {
    PARSELY.beacon.trackPageView(event);
  } else {
    parselyPreload.eventQueue.push(event);
  }
}

// when Parse.ly is done loading, flush the queue
window.PARSELY = window.PARSELY || {
  autotrack: false,
  onload: function() {
    parselyPreload.loaded = true;
    for (var i = 0; i < parselyPreload.eventQueue.length; i++) {
      PARSELY.beacon.trackPageView(parselyPreload.eventQueue[i]);
    }
  }
};

Example use cases

The following examples are necessarily simplified for illustration purposes, and are not meant to be used as-is. Any dynamic tracking logic should be customized and tailored to your specific site.

Transforming non-standard campaign parameters to supported parameters

The Parse.ly dashboard can display detailed campaign data when you use supported parameters. If you’re already using non-supported parameters to track campaigns in other systems, it’s possible to re-format those before sending a Parse.ly pageview.

*Example: Convert src parameters to utm_source before sending a Parse.ly pageview (so the values will be collected under the “Campaign Source” in the dashboard):*

window.PARSELY = window.PARSELY || {
  // disable automatic tracking
  autotrack: false,
  onload: function() {
    // will be called once, when the tracker loads
    function renameParams(rawUrl, oldParam, newParam) {
      // modify or replace this function as necessary
      // a regex replacement is sufficient in this scenario,
      // but more complicated situations might require
      // parsing parameters or further transforming their values
      var re = new RegExp("(.*?[&?])(" + oldParam + ")(?==)")
      return rawUrl.replace(re, "$1" + newParam);
    }
    // dynamically send a pageview with a modified url
    window.PARSELY.beacon.trackPageView({
      url: renameParams(location.href, "src", "utm_source"),
      urlref: document.referrer,
      js: 1
    });
  }
};

// insert the parsely tracker code here...

Using GTM

Built into the Parse.ly GTM tag template is the ability to configure a dynamic tracking tag. This allows you to leverage the tools of your GTM container to configure when you want to trigger the dynamic pageview.

You can use the GTM dynamic tracking tag even if you have implemented the Parse.ly tracker via another method (e.g. the WordPress plugin or hardcoded). You just need to ensure the PARSELY object has been loaded before triggering the tag.

Last updated: January 02, 2024