Categories: Microsoft Clarity
*** NOTE: ALL INFORMATION IS ACCURATE AT DATE OF PUBLISHING ***

If you’ve been following along in the Microsoft Clarity blog series I have been doing, and you also work in the Power Platform world, you might have started thinking, oooh, I wonder if I could use this in a Power Apps Portal? The answer is YES, and combined with adding in some Custom Tags, it’s a great way to be able to review the visits to the portal, and filter the data in a variety of different ways. Read through this post first so you understand how Custom Tags are added, then in this post, I will provide six examples of the kind of custom tags you could add for your portal traffic.

Adding the initial Clarity tracking script can be achieved in the same way that I laid out in this post that explains how to add Google Analytics tracking code to a portal. So if you haven’t already, read through that and just use the Clarity tracking code, which you can read more about here. Once you’ve got that added, you can then use Liquid to pass through various values so that you can filter the data back into Clarity. If you don’t know anything about Liquid, you can read this for an intro. There are also some wonderful people to check out who do a ton on portals and Liquid specifically: Nick Doelman, Nicholas Hayduk, Jim Novak & Colin Vermander – all with varying levels of technical difficulty in terms of what they explain.

Before you embark on adding tags, be sure you have read through the Microsoft Clarity Terms & Conditions. Don’t pass values that could cause you to be in breach of these. It’s your responsibility to determine what you can or can’t (or shouldn’t) pass through to Clarity from the portal. The first tag I wanted to create was the ability to send the name of the Account related to the Contact logged in to the Portal. This way, I could see all visits for anyone linked to the same Account. This can be achieved by setting the KEY of Account and then using liquid to set the name of the Account as the VALUE.

 clarity("set", "Account", "{% if user %}{{ user.parentcustomerid.name }}{% endif %}");

This provides us with an Account tag, with a list of all the Accounts for any of the users who have logged on. Keep a couple of things in mind…. the list will only populate as users log in, and currently it will not be sorted alphabetically. Depending on how many Accounts you have, and users related to them, this list could get REALLY long… and there is no way to filter it.

Next, we can add in a new line with the KEY of Contact, and set the Full Name of the Contact as the VALUE.

    clarity("set", "Contact", "{% if user %}{{ user.fullname }}{% endif %}");

As with the Account filter above, this will give us a list of the Contacts as they log in. This is likely to be even longer than your list of Accounts, so think about how realistic the usability of this is.

I also thought it might be interesting to filter data based on the security level of the user based on the Web Role they have been assigned. This works great when you only have one Web Role assigned to a Contact. The liquid will check the user roles and see if it contains Administrators or Authenticated Users and set a VALUE accordingly. If it has neither of those, the VALUE will be set to Anonymous. Consider the Web Roles you have for your Portal, and you can use those in the liquid as required.

clarity("set", "User Type", "{% if user.roles contains 'Administrators' %}Administrator{% elseif user.roles contains  'Authenticated Users' %}Authenticated{% else %}Anonymous{% endif %}");

Now we can clearly filter the data in Clarity to show only those visits and recordings based on the type of user who they relate to.

All of the lines of code above can be used in the main Clarity code and added to the Header Web Template. Each line can be added on a new row. Adding all of the tags above to the header file makes sense, as that means it will trigger for every page viewed.

Here is the full code I used. All you need to do is replace the PROJECTID part with the project ID provided in the script provided by Clarity in your own environment. Put it all at the very top of the header file before anything else.

<script type="text/javascript">
    (function(c,l,a,r,i,t,y){
        c[a]=c[a]||function(){(c[a].q=c[a].q||[]).push(arguments)};
        t=l.createElement(r);t.async=1;t.src="https://www.clarity.ms/tag/"+i;
        y=l.getElementsByTagName(r)[0];y.parentNode.insertBefore(t,y);
    })(window, document, "clarity", "script", "PROJECTID");
    clarity("set", "Account", "{% if user %}{{ user.parentcustomerid.name }}{% endif %}");
    clarity("set", "Contact", "{% if user %}{{ user.fullname }}{% endif %}");
    clarity("set", "User Type", "{% if user.roles contains 'Administrators' %}Administrator{% elseif user.roles contains  'Authenticated Users' %}Authenticated{% else %}Anonymous{% endif %}");
    </script>

Another filter I thought might be useful is the ability to look at recordings if they included a search of some kind. This needs no liquid at all, and we can just set the KEY to be Search Included, and the VALUE to be Yes. We just need to determine WHEN that tag will trigger.

clarity("set", "Search Included", "Yes");

To do this, I went to the standard Search Web Page, then to the localised content. From there, on the Avanced tab, we just need to add in the line of code without the script tags.

Adding it to the Search page means it’s only going to be triggered if someone does a search and is then taken to the results page. This then gives us the ability to filter the data to see recordings and details ONLY if the entire visit includes a search.

Another option to filter the data might be to see how a new user navigates around the portal. This could be done easily if you use the Terms & Conditions functionality on the portal. You can read all about how to add T’s & C’s in this blog post from my friend Elaiza Benitez: Terms and conditions for GDPR in Dynamics Portals ~ Benitez Here. We will use this script to set the KEY of New User to the VALUE of Yes.

<script type="text/javascript">
    clarity("set", "New User", "Yes");
</script>

This script should only ever trigger when the Terms and Conditions copy is read, so on the Content Snippet where the T’s & C’s were added, click on the HTML tab and add the script right at the top.

Now when someone first logs in and they are shown the terms and conditions to agree to, the script will fire and the custom tag value will be sent to Microsoft Clarity.

This last one gave me the biggest challenge. I wanted to see if could filter traffic to show data and recordings where someone had viewed a Knowledge Article during the visit. I quickly realised that the way in which the KA pages worked was different to all others. I couldn’t just use liquid directly in the template (you can’t access it) and the KA number was only accessible from the URL. I tried various ways to extract it from the URL string, and get pretty close… then I found this post from Nicholas Hayduk that explained more about it, and also had a neater way to extract it: PowerApps Portals: Knowledge Articles and Liquid. I modified the fetch a little bit as I only needed the article public number attribute, and also needed to make sure I wasn’t getting a cached number from a different page. Basically, the script below gets the URL, splits it using the / character, then gets the second to last part of the URL which contains the article public number value. Then using fetchXML, we get the correct article record using that article public number as the search criteria to filter. Finally, at the bottom, I can then use liquid to pass through the article public number. Phew! So a bit more to it with this one!

{% assign urlSplit  = request.path | split: '/' %}
{% assign urlSplitLength  = urlSplit | size %}
{% assign kaCodeIndex = urlSplitLength | minus: 2 %}
{% assign kaCode = urlSplit[kaCodeIndex] %}
{% assign cacheString = request.params['cacheString'] %}  
{% fetchxml articlefetch %}
    <fetch version="1.0" output-format="xml-platform" mapping="logical" distinct="false">
      <entity name="knowledgearticle">
      <attribute name="articlepublicnumber" />
        <filter type="and">
          <condition attribute="articlepublicnumber" operator="eq" value="{{kaCode}}" />
          <condition attribute='articlepublicnumber' operator='ne' value='{{cacheString}}' />
        </filter>
      </entity>
    </fetch>
{% endfetchxml %}
{% assign article = articlefetch.results.entities[0] %}
clarity("set", "Knowledge Article", "{{ article.articlepublicnumber }}");
}

For this code, I added it to the localised content > advanced tab on the Knowledge Base – Article Details Web Page. That way it only triggers when someone is actually looking at a Knowledge Article.

And now we can see that the article number is passed back through as a VALUE for the Knowledge Article KEY we added in the code. If you didn’t care about getting the number and just wanted to know if someone had viewed ANY KA within their visit, you could add this to the Web Page instead:

clarity("set", "Knowledge Article", "Yes");

So, those are just some suggestions, and please make sure you do your due diligence and determine what you can pass through and if indeed you should be passing it through to Clarity. What do you think? Any other ideas for custom tags for your Power Apps Portal data?

You can watch a video on this here.


Check out the latest post:
Adding Existing Contacts To Subscription Lists


This is just 1 of 305 articles. You can browse through all of them by going to the main blog page, or navigate through different categories to find more content you are interested in. You can also subscribe and get new blog posts emailed to you directly.


2 thoughts on “Microsoft Clarity & Power Apps Portals

  1. Awesome write up and really great examples, thanks Megan 🙏 I’m going to put these into action for user friendly reports/filters within Clarity as well as capturing the account and contact GUIDs for embedding pre-filtered Power BI roles on contact and account records in Dynamics (assuming that there’ll soon be a Power BI connector for Microsoft Clarity 🤞)

    1. Glad you found them helpful! It was a good challenge thinking of the examples and then figuring out how I could use them. Hope they help on your projects!

Leave a Reply

Your email address will not be published. Required fields are marked *