Sunday, January 8, 2023

Setting User Expectations - Part 1

One of the main gripes from Citrix administrators are clients complaining that Citrix is slow when the issue is not anything in the Citrix infrastructure, but rather at the user's endpoint. This can include issues such as the user's PC (e.g. slow or pegged CPU), or a weak Wi-Fi connection. 

In this 3-part series, I will show you how to set the user's expectations before they even log on by placing what I call a QoS (Quality of Service) indicator on your NetScaler's logon page. This is accomplished by measuring what is known as Time To First Byte (TTFB). TTFB is a metric that measures the time between the request for a resource and when the first byte of a response begins to arrive by downloading a very small file from the NetScaler.

For this series, we will be using firmware version 13.1 of NetScaler, and we will be using the RfWebUI (Receiver for Web UI) theme. The tool we will use for most of our work will be WinSCP - a free secure copy utility (

In Part 1, we will get the basics of the QoS indicator done, and when finished, it should look something like this:

We begin by creating a NetScaler theme which will contain the look and feel of our customizations. The easier way to do this is by opening up a PuTTY (terminal emulation software) session to the primary node and entering:

add vpn portaltheme QoS -basetheme RfWebUI

These changes will be replicated from the primary node to the secondary node. Make sure you make these changes to the primary, or they will be removed the next time the config is synched from the primary node.

The above command will create a new theme called QoS in the following directory: /var/netscaler/logon/themes. 

Open the file /var/netscaler/logon/themes/QoS/css/theme.css and insert the following:

#QoSinfo {
   color: #fff;
#QoStext {
   font-family:'Open Sans', sans-serif;
#QoStext a {

Then save the file.

We then need to make a backup up of the following file on the NetScaler: /var/logon/LogonPoint/tmindex.html.  Open the file. Around line 386, you should see:

<div class="logon-spacer"></div>

Add the following lines between <div class="logon-spacer"> and </div>:

<div id="QoSinfo">
  <div id="QoStext">&nbsp;</div>

This is where the QoS indicator will be inserted on the screen.

When done, it should look like this:

The final step will be to insert the JavaScript code for the Time To First Byte calculation and to insert the result into the QoStext <div> above.

Scroll to the bottom of the file and locate the following two lines:

<script src="receiver/js/ctxs.core.min.js"></script>
<script src="receiver/js/ctxs.webui.min.js"></script>

Insert the following:

     var testImgUrl = "https://" + location.hostname + "/vpn/images/Tick32.gif";
     function checkLatency(url, callback) {
        var t=[], n=2, tcp, rtt;
        var ld = function() {
           t.push(+new Date);
           if(t.length > n) {
           else {
             var img = new Image;
             img.onload = ld;
             img.src=url+"?" + Math.random() + '=' + new Date;
    function displayQoS(latency) {
         var QoStext = document.getElementById("QoStext");
         for (i=0; i<aLatencyRanges.length;i++) {
            if(latency<=aLatencyRanges[i][0]) {
                var QoSclass = aLatencyRanges[i][1];
                var QoSrange = aLatencyRanges[i][2] + ' (' + latency + ' ms.)';
                 QoStext.innerHTML = 'Connection Strength:<br>'+QoSrange; 
    function runQoS() {
       checkLatency(testImgUrl, displayQoS);


Then save the file. Note: if you have an HA pair, any changes to this file must be done to both NetScalers - source code changes are not replicated between the nodes.

That's it! In Part 2, we will add a graphical representation of the QoS indicator.