Sending manual updatePageActivity after trackPageView

I’ve been testing the sending of an updatePageActivity page ping. This manual page ping will send if I do it before the trackPageView. However, if I fire a manual page ping after trackPageView, the manual page ping will not send.

The doc (https://github.com/snowplow/snowplow/wiki/2-Specific-event-tracking-with-the-Javascript-tracker#pagepings) says that enableActivityTracking must be called before trackPageView - ok. Doing that I will start automatic page pings on the specified intervals - all good there. Though it doesn’t specifically say that updatePageActivity must happen before trackPageView this seems to be the case. Can you confirm that this is true?

For this particular unusual use case I want to send page pings manually after trackPageView and that doesn’t seem possible.

Thanks,
JB

Hi @JBATX

UpdatePageActivity isn’t designed to manually send page pings, it exists to update the time the tracker last logged activity of the user. This is important as Page Pings only fire if the user is active on the page (scrolling, mouse movement, etc.) so for content where the user is inactive (playing a video), you will want to fire UpdatePageActivity calls to tell the tracker that the user is still active and it should send page pings when the next heart beat occurs.
Activity Tracking works by checking for activity within each heartbeat, so if the heartbeat is set to 10 seconds then there must have been some activity on the page in the last 10 seconds for the page ping event to be sent.

If you wish to send Page Pings manually, this is a little tricky! Currently, sending a Page Ping event isn’t part of the public API of the tracker.

You could perhaps mimic this by sending a custom page ping as a self describing event and then deal with your custom page ping event as data modelling step. Getting the values out of the tracker to be able to do this will require you to use the new Activity Tracking callback function (in 2.13.0).

I’m curious what your use case is for sending a manual page ping and how you intend to deal with this when modelling it with the “standard” page pings? You’d end up with unevenly spaced page ping events, which is a much harder to deal with and infer activity from.

I hope this example might help you instrument what you are after, if you want to try the custom page ping idea:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8"/>
        <script type="text/javascript" async=1>
            ;(function(p,l,o,w,i,n,g){if(!p[i]){p.GlobalSnowplowNamespace=p.GlobalSnowplowNamespace||[];
            p.GlobalSnowplowNamespace.push(i);p[i]=function(){(p[i].q=p[i].q||[]).push(arguments)
            };p[i].q=p[i].q||[];n=l.createElement(o);g=l.getElementsByTagName(o)[0];n.async=1;
            n.src=w;g.parentNode.insertBefore(n,g)}}(window,document,"script","sp.js","snowplow"));
        </script>
        <script>
            window.snowplow('newTracker', 'sp', '<<collector_url>>', {
                appId: 'activity-test',
                eventMethod: 'post',
                contexts: {
                    webPage: true
                }
            });

            var aggregatedEvent = {
                pageViewId: null,
                minXOffset: 0,
                maxXOffset: 0,
                minYOffset: 0,
                maxYOffset: 0,
                numEvents: 0
            };
            window.snowplow('enableActivityTrackingCallback', 10, 10, function () {
                aggregatedEvent = {
                    pageViewId: event.pageViewId,
                    minXOffset: aggregatedEvent.minXOffset < event.minXOffset ? aggregatedEvent.minXOffset : event.minXOffset,
                    maxXOffset: aggregatedEvent.maxXOffset > event.maxXOffset ? aggregatedEvent.maxXOffset : event.maxXOffset,
                    minYOffset: aggregatedEvent.minYOffset < event.minYOffset ? aggregatedEvent.minYOffset : event.minYOffset,
                    maxYOffset: aggregatedEvent.maxYOffset > event.maxYOffset ? aggregatedEvent.maxYOffset : event.maxYOffset,
                    numEvents: aggregatedEvent.numEvents + 1
                };
            });
            window.snowplow('trackPageView');

            function sendPagePing() {
                //Send whatever custom event you wish when you need your "custom" page ping.
                window.snowplow('trackSelfDescribingEvent', {
                    schema: 'iglu:com.acme_company/page_ping/jsonschema/1-0-0',
                    data: {
                        minXOffset: aggregatedEvent.minXOffset,
                        maxXOffset: aggregatedEvent.maxXOffset,
                        minYOffset: aggregatedEvent.minYOffset,
                        maxYOffset: aggregatedEvent.maxYOffset,
                        activeSeconds: aggregatedEvent.numEvents * 10
                    }
                });
            }
        </script>
    <body>
        <input type="button" onclick="sendPagePing()" value="Send Page Ping" />
        <img src="http://via.placeholder.com/1000x1000.png?text=Scroll" /><br/>
        <img src="http://via.placeholder.com/1000x1000.png?text=for" /><br/>
        <img src="http://via.placeholder.com/1000x1000.png?text=activity" /><br/>
        <img src="http://via.placeholder.com/1000x1000.png?text=tracking" /><br/>
    </body>
</html>
2 Likes

@PaulBoocock vey helpful! Thank you. Our product is a browser extension that helps manage policy compliance. It’s installed by corp IT departments. We have sp instantiated in the “background” of the extension. This is done to protect the sp object from pages that we have no actual control over and to prevent CORS issues. Our extension supports and monitors over 1000 websites in our industry. Our “content scripts” communicate with the background’s listener which determines what sorts of events to send to the collector. We send events about the extension itself and also the pages and tabs that are active. For this particular issue, I needed to be able to receive a message from the content script (using setInterval or _.debounce) and send a page ping from the background. Initially, using page pings seemed to make sense. However, I elected to use structured events as that allows me to set se_category = <tab | extension>, se_action = ping, se_label = whatever contextual details. This gives more context to the event. Much of the details that sp needs are derived from querying the tabs and then manually setting them for sp. x-real-ip for our collector URL is manually set. href, referrer are all derived from the tabs API and manually set.

1 Like

That sounds like a good solution to me! Glad you found a method that works for your use case :slight_smile:

Given your use case, I also wonder if you could have called UpdatePageActivity in a setInterval to simulate activity on the page and therefore send page pings with enableActivityTracking. I haven’t tested this but the thought just popped into my head!

There isn’t actually an sp object in the page proper, it only exists in the extension’s background. I was calling UpdatePageActivity in the background in response to the page’s content script sending a message to the background listener. That’s the part that seemed to not work. …But, now that I better understand how it’s supposed to work - I should retest.

1 Like