How to get page view events in single-page application (AngularJS)?

Hi all! I previously attended a webinar where there was a QA on single page applications (like AngularJS) and the workarounds required to properly fire off pageview events, I don’t seem to find it anymore as the URL for the blog post doesn’t exist anymore.

I found this which didn’t quite give me the answer I was looking for Single Page Application and Javascript Tracking issues

So the problem I am facing is that, in an AngularJS application a page view event is only fired whenever a new page is open or loaded, that is for each page only one page view event will appear and no other when navigating in the app (through link clicks, browsing, form submits, etc).

Is there a way to still invoke these “virtual page views” as page view events in Snowplow with the Javascript tracker? The only solution I have now is to aggregate all page ping events on that same session/page to know that they entered that page. Is it the same argument as the link provided that we must make sure for clicks/listeners to fire off the page view event?

What is the solution here? Best practices? Any advise is welcome!


Hi, we have an Angular 9 application so not the same as AngularJS.

We have used a router guard to fire virtual page views:
On the canActivate method you have access to ActivatedRoute which includes the full URL to navigate to (path, query, etc). You need to pass this info on to the snowplow trackPageview method.

In case you want to have multiple trackers like GA and SP you can also look into . GA is supported out of the box and writing a provider for Snowplow is not that difficult.

Kind regards,


You can fire page views whenever you like using trackPageView with the Snowplow JavaScript tracker. This function works for single page applications, assuming you are using newer versions of the tracker, ensure you call the function within your routing and not when the application loads and you should be fine. I built out a simple Angular example a little while ago here that might help: (although not AngularJS).

We’ve got a new version (v3) coming out soon (Q1 2021) that will offer much better support for Angular apps (via npm) but unfortunately that doesn’t quite help you right now.

We recently integrated into which you might find useful, that offers a more “modern js” approach to tracking with Snowplow until v3 arrives.

1 Like

I have been thinking & checking this same thing (page view vs page ping) for a VueJS application, but actually our setting of minimum page visit of 5 seconds and page ping 30 sec interval is quite OK for us because we have content that the users should be “consuming”.

Original case is similar to who started this thread; also for us clicking and rendering Vue page with Vue router doesn’t out of box fire the page view event. As per Paul’s answer we could of course tie it into our source code, but with explanation above it might even be better that user randomly clicking pages not fires the views, compared to opening a page and getting the ping after 5 seconds.

actually, I haven’t yet gotten into installing Dbt for aggregating data, I need to find out if the lacking page_view screws up the aggregation… :upside_down_face:

I need to find out if the lacking page_view screws up the aggregation…

It would, for two reasons:

  • Page view IDs rotate on the page view event. So your pings for several pages will be attributed to just the one in the standard web model unless you’re rotating the ID.
  • Page views are the ‘base’ event to aggregate in the standard web model - with no page view you won’t have a row, even if rotating the page view ID.

Of course it’s likely possible to come up with a modified model or your own modeling logic for the tracking you have, but the easiest way to achieve a symbiotic relationship between tracking and our models is to call trackPageView when you want a new page view to be registered (you could delay for 5s before calling it to achieve the same effect you describe - I tend to think it’s better to collect those ‘clicking around’ page views too, as they do tell you something about the behaviour/intent of user. Of course it’s totally valid to prefer not to have them).


yeah thanks for clarification @Colm . I was hoping this all could be done without source code changes but seems we need to add the trackPageView then :cold_sweat:

thanks @Colm for earlier clarifications, we did implement trackPageView into VueJS router. Now the events are more extensive. I believe “router.afterEach()” is a good place for this :slight_smile: If here are any VueJS developers using Vue router, I am happy to receive any comments for hooking page views.