Know your users, tailor the user experience

We support 45 000 users who are distributed globally, using all kinds of devices with all sorts of browsers.

Qlik Sense logs very little about them, but what if… what if there was a way to know more? What if we could understand how they use Qlik Sense in order to better serve them?

Wish list

Here is my wish list: “Dear Santa Qlik, I want to know what users experience and details about…

  • Initial application load time on the device
  • Time to load another sheet
  • Application navigation path
    • Do they use the base sheets (what we have delivered) or rather the community sheets (what they have built on top)?
  • Activity type, i.e. browsing the hub, an app sheet, app story, data load editor, …
  • Country/Region location of the user
  • Network performance, some indication about bandwidth and latency
  • Device, i.e. laptop, iPhone/iPad, Android
  • Browser, i.e. IE, Chrome, Edge, Safari, Firefox or the Qlik Sense mobile app
  • Error messages, typically device/browser related

Thanks for making a miracle!

Your faithful Qlik addict”.

If you like this idea, please vote on the Qlik feature idea: Support-for-web-analytics-trackers

What would I do with that?

Well, if Santa Qlik would somehow hear my demand, I could probably better understand what is the perceived user experience with our Qlik Sense instances. Is it fast enough? If it is not, what could we do about it? Who is impacted the most and can we build a business case to solve that problem?

Network latency

When facing performance issues, the most common answer is to redesign a Qlik Sense application. Of course that helps, however, even the best designed apps don’t close the gap of distance between your servers and your users.

When your server is located in the US and the users access it from the other side of the planet, then they have to deal with network latency. It’s down to physics, there is no optimal data model that can solve that. However, IT can instantiate another Qlik Sense instance closer to the users.

Device performance

The diversity of devices and browsers will likely lead to few users raising performance issues. It’s difficult to tell what is the root cause of performance issues.

Knowing what is the experience of other users, in terms of application load time and navigation, with different network conditions, devices and browsers on the very same app can definitely help.

Application design

You had several business workshops, the business requirements were refined, then implemented. You look at the Qlik application “Sessions Monitor” and you see a great level of adoption, awesome!

Are you sure that everyone is actually using the sheets that were developed? Or have they built their own sheets, better tailored to their actual needs? You cannot tell that from the “Sessions Monitor”.

Knowing the application navigation path will help understand the user journey within the app, what they use, if community sheets should replace the base ones and better understand their actual zone of interest.

Proactive monitoring

Why would you have to wait for application incidents to pile up in your inbox?

Real-time user experience insights enable you to proactively monitor the platform, get alerts and fix issues before they escalate.

Web Analytics

If you’re a seasoned Qlik expert, you probably know that none of these metrics are available out of the box. We typically record them with the help of web analytics trackers, like the famous Google Analytics, or AppDynamics in my case.

These solutions are rather simple to implement, once you have setup your account, all you need is to add a tracker in a web page. This tracker needs to be loaded first, so that it will capture the whole user experience. I will repeat this on purpose, this tracker needs to be loaded first, first, first, first. First I said!

Right, so how do we make sure it loads first then? We add the tracker into the HEAD section of the HTML content.

3 solutions

1. Mashup: Embed a tracker within a mashup: you have full control over them, it will work nicely. By doing so, you will however only capture web analytics about your mashups, which in most cases is a tiny part of all the Qlik Sense activities.

2. Extensions: Embed a tracker within a Qlik Sense extension: you have to add that extension to every app sheet.
It works. It works, but you never know in which order the objects of a sheet will get loaded, so you cannot expect to capture the whole page load. Also, if the extension was not added to a sheet and the extension was not loaded previously from another sheet, then you will not capture anything.

3. Drum roll, my favorite!

My favorite option

The Qlik Sense content is served dynamically, I am referring to the hub, the application client, the QMC, everything.
There is a folder where root HTML content is stored, what’s served first to the web clients, and we can modify that HTML content, technically we can.
Disclaimer: What follows is NOT a recommendation, but only for awareness.

Qlik support will not encourage you to change these files and they will probably not support you if you do make the change, and later face issues.

Again, If you like this idea, please vote on the Qlik feature idea: Support-for-web-analytics-trackers

On your proxy node, these web files will be stored under your installation folder within …\Qlik\Sense\
The proxy node could be, for instance, on your central node within this folder: C:\Program Files\Qlik\Sense\

These files are different with each Qlik Sense version and their respective contents refer to resources with version specific names. In other words, note to yourself, the files will be overriden with every version upgrade.

Note to the architect in the room

From this point, if one’s unsure, it is wisest to abstain.

Whatever you touch, take a backup copy of it, BEFORE you touch it.

In my case, I want to track the user experience within the hub, browsing to the streams and list of apps, then within apps and the app navigation.

I have therefore edited both the hub.html and client.html files.

  • The hub.html file is used whenever the users will access the Hub.
  • The client.html file is used whenever the users will open an application, from the Hub or from a direct link.

There are other base pages, like the QMC, I leave it up to you to decide what you want to track.

You have to edit the files, insert your tracker just after the <HEAD> tag:

Once done, you need to restart all services (except the Repository DB and the Logging services). To keep it simple, with service dependencies, you can restart first the Repository service, then the Dispatcher service.

You’re done, you can access your Qlik Sense site and start collecting web analytics.

As usual with everything you do at a platform level, I recommend you check your ecosystem on a sandbox site before you roll out such configuration changes to other systems.

I have personally used AppDynamics to track the user experience. Since there is a lot more to say and to share, I will write a dedicated article about it.

This will cover how to handle the API, but also how to enrich the data from the Qlik Sense repository to map URLs changes with user activities and navigation.

Known Issues

It is possible that a few extensions may not work fine: They may conflict with your tracker. In such a case, you can check the list of optional tracker parameters, or work with the extension developers.

It is also possible that Qlik sessions won’t time out anymore while the browser is open, due to the active mechanism of the tracker.


Pretty handy to also capture who was logged in that Qlik session.

In case you want to capture the logged user and directory details from the session cookie, below is some sample code you can adapt to your own web analytics tracker:

function extractUserData() {
    var cookies = document.cookie.split(';');
    for (var i = 0; i < cookies.length; i++) {
        var cookie = cookies[i].trim();
        if (cookie.indexOf('name') === 0) {
            var user = cookie.substring(5);

        if (cookie.indexOf('directory') === 0) {
            var directory = cookie.substring(10);

    return {
        userData: {
            userName: user,
            userDirectory: directory,
            hash: location.hash,
            appName: document.title