{"id":135,"date":"2016-04-20T21:22:10","date_gmt":"2016-04-20T21:22:10","guid":{"rendered":"http:\/\/www.digitaldatatactics.com\/?p=135"},"modified":"2018-03-01T19:53:24","modified_gmt":"2018-03-01T19:53:24","slug":"how-do-i-use-dtm-for-a-single-page-app","status":"publish","type":"post","link":"https:\/\/www.digitaldatatactics.com\/index.php\/2016\/04\/20\/how-do-i-use-dtm-for-a-single-page-app\/","title":{"rendered":"How do I use DTM for a Single Page App?"},"content":{"rendered":"<p>The question of how to use DTM on Single Page Apps (SPAs) is a VERY hot item right now. By Single Page App, I&#8217;m referring to\u00a0a full user flow contained on a single web page, so as to provide the user a more seamless experience. Often, these pages act like typical web pages, but they don\u2019t always change URLs or load new resources.\u00a0Many common web development technologies, such as Angular.js, Ember.js, and AJAX use SPA principles.<\/p>\n<p>Unfortunately, there isn&#8217;t a single great answer for how to deploy DTM- it depends on many things. I&#8217;ll work through some of the options and the limitations to be aware of.<\/p>\n<h3>Suppressing Page View Beacons<\/h3>\n<p>Whatever method you take for tracking page views in a SPA, keep in mind most SPAs\u00a0<em>do<\/em> have one true &#8220;page view&#8221; when the DOM first loads. If you are going strictly with the DCR or EBR route, you may <a href=\"http:\/\/www.digitaldatatactics.com\/examples\/DCRsuppress.html\">need to suppress the initial page view beacon<\/a> the Analytics tool will want to set by default. Otherwise, in the example below where the developers are firing a direct call rule on all page views, you&#8217;d get TWO beacons on the first page and 1 on all subsequent pages.<\/p>\n<p><a href=\"http:\/\/digitaldatatactics.com\/wp\/wp-content\/uploads\/2016\/04\/Picture1.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-152\" src=\"\/\/digitaldatatactics.com\/wp\/wp-content\/uploads\/2016\/04\/Picture1.png\" alt=\"Picture1\" width=\"933\" height=\"347\" srcset=\"https:\/\/www.digitaldatatactics.com\/wp\/wp-content\/uploads\/2016\/04\/Picture1.png 933w, https:\/\/www.digitaldatatactics.com\/wp\/wp-content\/uploads\/2016\/04\/Picture1-300x112.png 300w, https:\/\/www.digitaldatatactics.com\/wp\/wp-content\/uploads\/2016\/04\/Picture1-768x286.png 768w\" sizes=\"(max-width: 933px) 100vw, 933px\" \/><\/a><\/p>\n<h3>Data Layer Considerations<\/h3>\n<p>You&#8217;ll need to make sure that whatever the sources of your Data Elements are (CSS selector, javascript objects, cookies&#8230;) have the correct values BEFORE your rule is triggered. I have an <a href=\"http:\/\/www.digitaldatatactics.com\/examples\/SPAdl.html\">example site showing one way you might do this <\/a>for a data layer\u00a0(though you&#8217;ll need to look in the source code), but ultimately it&#8217;s going to depend on your site.<\/p>\n<h3>Variable Persistence<\/h3>\n<p>One last consideration is that once your Analytics object exists (as in, the &#8220;s&#8221; in &#8220;s.pageName&#8221;), variables set on it will continue to exist unless specifically overwritten. In most cases, you&#8217;d overwrite s.pageName with a new value so it isn&#8217;t a problem, but something like s.eVar5 may be set on the first beacon in your SPA, and not desired on subsequent beacons. You can use s.clearVars() to &#8220;refresh&#8221; your &#8220;s&#8221; object, but you have to make sure it fires at the right time- for example, after the beacon on Page A, but before DTM starts mapping Data Elements to variables for the beacon on Page B.\u00a0How you do this will depend on the overall deployment method you choose.<\/p>\n<h3>Deployment Methods<\/h3>\n<h4>1) Direct Call Rules<\/h4>\n<p>Perhaps the most straight-forward approach is to have developers fire a Direct Call Rule, like _satellite.track(&#8220;page view&#8221;) on every thing YOU consider a page view, whether it&#8217;s a fresh new DOM or not.<\/p>\n<table>\n<tbody>\n<tr>\n<th width=\"50%\"><strong>Advantages:<\/strong><\/th>\n<th width=\"50%\"><strong>Disadvantages:\u00a0<\/strong><\/th>\n<\/tr>\n<tr>\n<td>\n<ul>\n<li>You have ultimate control over when a page view in considered a page view.<\/li>\n<\/ul>\n<\/td>\n<td>\n<ul>\n<li>If you need to clear out variables between beacons (for instance, you set s.eVar5 in the first beacon in the SPA, and don&#8217;t want it in the second beacon), Direct Call Rules don&#8217;t provide a great place to use something like s.clearsVars(). There are some <a href=\"http:\/\/www.digitaldatatactics.com\/examples\/DCR.html\">potential work-arounds<\/a>, but none are ideal.<\/li>\n<li>Developers need to add more DTM-specific code (satellite.track) to your pages.<\/li>\n<li>Direct Call Rules don&#8217;t allow for extra conditions (like &#8220;fire THIS logic on pageA, and THAT logic on pageB&#8221;)\u00a0in the interface.<\/li>\n<li>Direct Call Rules don&#8217;t &#8220;stack&#8221;- if multiple rules have conditions that are met, multiple rules will fire.<\/li>\n<\/ul>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h4>2) pushState or hashChange<\/h4>\n<p>Many SPA frameworks, like Angular, use a certain flag to let the browser know the user is viewing a new &#8220;page&#8221;.<\/p>\n<p><a href=\"http:\/\/digitaldatatactics.com\/wp\/wp-content\/uploads\/2016\/04\/pushState.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-151\" src=\"\/\/digitaldatatactics.com\/wp\/wp-content\/uploads\/2016\/04\/pushState.png\" alt=\"pushState\" width=\"419\" height=\"83\" srcset=\"https:\/\/www.digitaldatatactics.com\/wp\/wp-content\/uploads\/2016\/04\/pushState.png 419w, https:\/\/www.digitaldatatactics.com\/wp\/wp-content\/uploads\/2016\/04\/pushState-300x59.png 300w\" sizes=\"(max-width: 419px) 100vw, 419px\" \/><\/a><\/p>\n<p>DTM can listen for this flag in an Event Based Rule using a <a href=\"http:\/\/www.digitaldatatactics.com\/examples\/pushState.html\">pushState or hashChange condition<\/a>.<\/p>\n<table>\n<tbody>\n<tr>\n<th width=\"50%\"><strong>ADVANTAGES:<\/strong><\/th>\n<th width=\"50%\"><strong>DISADVANTAGES:\u00a0<\/strong><\/th>\n<\/tr>\n<tr>\n<td>\n<ul>\n<li>No additional code is needed- most SPA frameworks are already firing something DTM can listen to<\/li>\n<li>It&#8217;s an Event Based Rule, which allows you to fire clearVars(), and set extra conditions<\/li>\n<\/ul>\n<\/td>\n<td>\n<ul>\n<li>Because you are listening for an event set by the framework, you have less control over timing. Updating a data layer BEFORE the &#8220;pushState&#8221; event is detected would be critical.<\/li>\n<li>Event Based\u00a0Rules don&#8217;t &#8220;stack&#8221;- if multiple rules have conditions that are met, multiple rules will fire.<\/li>\n<\/ul>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h4>3) Custom Event EBR<\/h4>\n<p>Another option, which feels a bit like a blend of the first two options, is\u00a0to use a Custom Event-based Event Based Rule (and no, that&#8217;s not a typo- it&#8217;s an EBR based on the JavaScript Concept of a <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/CustomEvent\">Custom Event<\/a>). It&#8217;s possible Developers are already using this Custom Event concept for their own code and purposes, and DTM can just listen for it&#8230; or you can have developers set one specific to our DTM needs by using something like my <a href=\"http:\/\/www.digitaldatatactics.com\/index.php\/2016\/04\/20\/setting-up-an-event-based-rule-that-be-fired-directly-like-a-direct-call-rule\/\">digitalData.userAction hack<\/a>.<\/p>\n<table>\n<tbody>\n<tr>\n<th width=\"50%\"><strong>ADVANTAGES:<\/strong><\/th>\n<th width=\"50%\"><strong>DISADVANTAGES:\u00a0<\/strong><\/th>\n<\/tr>\n<tr>\n<td>\n<ul>\n<li>You have a little more control over timing<\/li>\n<li>It&#8217;s an Event Based Rule, which allows you to fire clearVars(), and set extra conditions<\/li>\n<\/ul>\n<\/td>\n<td>\n<ul>\n<li>May require more developer work- similar level of effort as DCRs<\/li>\n<li>Event Based\u00a0Rules don&#8217;t &#8220;stack&#8221;- if multiple rules have conditions that are met, multiple rules will fire.<\/li>\n<\/ul>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h3>\u00a04) (NEW OPTION!)\u00a0&#8220;dataelementchanged&#8221; Event Based Rule<\/h3>\n<p>Just in the last few weeks, a new option emerged as part of the AEM Context Hub integration. This allows DTM to listen for changes to certain data elements- for instance, you could have a rule fire whenever the &#8220;pageName&#8221; has changed. My friends at 33 sticks have a <a href=\"http:\/\/33sticks.com\/hack-adobe-dtm-respond-dynamic-data-layer-changes\/\">great blog post <\/a>about this already for more info.<\/p>\n<table>\n<tbody>\n<tr>\n<th width=\"50%\"><strong>ADVANTAGES:<\/strong><\/th>\n<th width=\"50%\"><strong>DISADVANTAGES:\u00a0<\/strong><\/th>\n<\/tr>\n<tr>\n<td>\n<ul>\n<li>You have a little more control over timing<\/li>\n<li>It&#8217;s an Event Based Rule, which allows you to fire clearVars(), and set extra conditions<\/li>\n<\/ul>\n<\/td>\n<td>\n<ul>\n<li>Requires careful consideration of when the data layer changes\/loads<\/li>\n<li>Event Based\u00a0Rules don&#8217;t &#8220;stack&#8221;- if multiple rules have conditions that are met, multiple rules will fire.<\/li>\n<\/ul>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n","protected":false},"excerpt":{"rendered":"<p>The question of how to use DTM on Single Page Apps (SPAs) is a VERY hot item right now. By Single Page App, I&#8217;m referring to\u00a0a full user flow contained on a single web page, so as to provide the user a more seamless experience. Often, these pages act like typical web pages, but they &#8230; <a title=\"How do I use DTM for a Single Page App?\" class=\"read-more\" href=\"https:\/\/www.digitaldatatactics.com\/index.php\/2016\/04\/20\/how-do-i-use-dtm-for-a-single-page-app\/\" aria-label=\"Read more about How do I use DTM for a Single Page App?\">Read more<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[7,23,47],"tags":[19,8,30],"_links":{"self":[{"href":"https:\/\/www.digitaldatatactics.com\/index.php\/wp-json\/wp\/v2\/posts\/135"}],"collection":[{"href":"https:\/\/www.digitaldatatactics.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.digitaldatatactics.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.digitaldatatactics.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.digitaldatatactics.com\/index.php\/wp-json\/wp\/v2\/comments?post=135"}],"version-history":[{"count":6,"href":"https:\/\/www.digitaldatatactics.com\/index.php\/wp-json\/wp\/v2\/posts\/135\/revisions"}],"predecessor-version":[{"id":276,"href":"https:\/\/www.digitaldatatactics.com\/index.php\/wp-json\/wp\/v2\/posts\/135\/revisions\/276"}],"wp:attachment":[{"href":"https:\/\/www.digitaldatatactics.com\/index.php\/wp-json\/wp\/v2\/media?parent=135"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.digitaldatatactics.com\/index.php\/wp-json\/wp\/v2\/categories?post=135"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.digitaldatatactics.com\/index.php\/wp-json\/wp\/v2\/tags?post=135"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}