Thursday, 12 November 2015

Using FXM with single page applications

I have recently been doing some work with FXM and as part of that a large portion of that work has been with using FXM on single page applications(SPA). While the Sitecore FXM  api provides functions for pushing events it doesn't provide a function for refreshing the context of the application as a whole. The following is the approach that I have used on a recent project. 

I should firstly caveat the above with the fact that this is based on Sitecore 8.0 Update 5 and there is a fair chance that this will approach will have been superseded in the future. 

If you set FXM up on a site hosting a single page application by default you will be able to send down content and track interactions on the first screen. But when the users start transitioning through screens, you will find that content targeted to those screens doesn't appear, content from the previous screen won't be removed and events targeting the second screen won't fire. From my investigations this appear to com about when the SPA updates or removes the DOM elements and FXM is not aware of the transition. So the question is how can we make FXM aware of the transition?

The first aspect is understanding how your SPA transitions. One of the key requirements however is that after the transition is complete that FXM will be able to understand the current state. This essentially means are there any page filter rules in Sitecore that can observe the current state.
The simplest of these to observe is a change in the URL, which if your SPA supports deep linking or the "back" button in the browser should be a part of the SPA.

Once you know how it transitions the next step is determine when it has transitioned, this is going to vary from SPA to SPA and you may need to work with the team developing the SPA to get some help. There are some approaches that are more common then others however:
  • There is often an even raised by the SPA when it transitions and with a bit of JavaScript debugging yo can probably discover it
  • A lot of the SPA frameworks provide and even similar to the above
  • Failing all else if the URL has change the location in the address bar has changed as well, so you can always poll it for changes
Now that we can observe the changes in state and we can filter our FXM content/actions to match that state we need to refresh the FXM context. At this stage the below will work, but I am hoping for a more refined approach in later versions of FXM. Essentially we need to remove FXm from the page and re-add it afterwards. This has the effect of tricking FXM into thinking it is responding to a new page view. To make this add/remove easier I recommend adding an id to the script tag in the beacon script when adding it to your external site.

        $( "#fxmScriptId" ).remove()
        $('body').append('<script id="fxmScriptId" src="//your-site/bundle/beacon" />' )

Please keep in mind the method that you use to reintroduce the beacon script to the page, as you need it to evaluate the JavaScript and some approaches won't do this.

If you have the above running you should see your tracking and content being served, but what you are probably also seeing is that the content from previous screens are not being removed. This is happening because we are just removing and re-adding the FXM beacon to the page and no one is doing a clean up. 

To get around this I recommend encapsulating all of your FXM content in a class that you can target during a transition. Once you have a way of targeting that content you can then remove during the transitions, similar to the below. One thing to keep in mind however is that this is best suited to the "insert after" and "insert before" approaches to injecting content, as opposed to the "replace" approach as it will not allows you to restore the content that has been replaced.

        $( "#fxmScriptId" ).remove()
        $( ".fxm-content" ).remove()
        $('body').append('<script id="fxmScriptId" src="//your-site/bundle/beacon" />' )

Now that we have all of the following wired up, when you transitions states through your SPA you should have both tracking and content matching the state of your SPA.