Dynamic Tracking

Note

Dynamic tracking can dramatically alter the results reported in Parse.ly's dashboard. Incorrect implementations of this dynamic call can result in skewed data.

Merely including the Parse.ly JavaScript tracker in your pages registers a pageview with Parse.ly's systems, unless you set PARSELY.autotrack to false as described below. However, there are also times when you may want to register multiple pageviews in a single page or track dynamic content -- for example, when tracking image slideshows or dynamic content.

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

<script>
    PARSELY = {
        // after PARSELY tracking code loads asynchronously
        onload: function() {
            // bind pageview tracking for all "next" links.
            // example event listener; set your own based 
            // on your site design
            jQuery("a.next").bind("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 -->

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 can't be relative paths (e.g. "/article" as opposed to "http://www.example.com/article")—they have to be full URLs.

The onload handler

Parse.ly's tracker code loads asynchronously, and 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 include, like this:

<script>
    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 -->

Dynamically sending a tracking call

To send a tracking request to the analytics server use PARSELY.beacon.trackPageView. It takes 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
});

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>
    PARSELY = {
        autotrack: false,
        onload: function() {
            // PARSELY.beacon.trackPageView({ ... })
        }
    };
</script>
<!-- START Parse.ly Include -->
<!-- ... as above ... -->
<!-- END Parse.ly Include -->

Subsequent events could then be tracked using dynamic tracking.

Crawling 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.

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.

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.

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. 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
PARSELY = {
    autotrack: false,
    onload: function() {
        parselyPreload.loaded = true;
        for (var i = 0; i < parselyPreload.eventQueue.length; i++) {
            PARSELY.beacon.trackPageView(parselyPreload.eventQueue[i]);
        }
    }
};
Do you have an urgent support question?