Related pages:

You can add user information that is specific to your application to a browser snapshot. The information is expressed as key-value pairs that are attached the JavaScript Agent configuration and later included in the beacons sent to the EUM Server.

The JavaScript Agent initializes user data differently depending on the page type (base, Ajax, virtual) and the method used (immediately invoked function expressions, function pointers, and literals). See Methods for Setting Custom User Data to learn when the JavaScript Agent initializes the user data for each page type and method.

The maximum size allowed for user data in a page is 2048 characters (CORS beacon) or 100 bytes (image beacon). The maximum size includes the keys-value pairs, syntax characters such as braces, and quotation marks.

View Custom User Data 

Custom user data appears in Browser Analyze, Browser Snapshots, and Sessions. View the following tabs to learn more about how user data is viewed and used in the Controller UI.

In this Browser Analyze screenshot, the user data vehicleYear is used to sort the records. You can also select fields to view user data.

Browser Analyze

This Browser Snapshots tab screenshot shows you how to filter results with user data.

Browser Snapshots

You view user data in the Session Summary of the Session Details dialog as shown in this screenshot. In sessions, the custom user data is only included when the base page with the custom user data is the first page of the session. 

Session Summary

Methods for Setting Custom User Data 

You can use several methods to set custom data for each page type (base, Ajax, virtual). Each method has its own syntax, execution time, and use case. This table outlines the execution time and potential use case for each method and page type.

Method TypePage TypeExecution TimePotential Use Cases
Immediately Invoked Function Expressions (IIFE)BaseThese are JavaScript functions that run as soon as they are defined. They're also known as self-executing anonymous functions.

If your base/virtual page or Ajax request depends on information from different resources, you can set static information for custom user data with IIFE.

For example, if two different server scripts generate content for the base page, you could use the IIFE on the client to set the static user data.

Ajax
Virtual
Function pointers

BaseThe JavaScript Agent executes function pointers when the onload event is triggered.Data extracted from cookies, the page, and meta data.
AjaxThis event is triggered when an Ajax call is made. Custom user data for the Ajax events are attached to AJAX requests.Meta data regarding the Ajax request such as the URL, HTTP method, or the request payload.
VirtualThis event is triggered when the virtual page is created. The virtual page is a dynamically recreated version of the base page, and custom user data set for VPageView events are attached to the virtual page records.Use if the information is derived or found somewhere on the page because of the creation of the virtual page. User-specific fields or user data set based on the URL and DOM changes.
Literals

BaseYou can simply use literal values to set custom data. The values, as with IIFE, are set as soon as the values are defined.Constants, static data extracted and set on the server.
Ajax
Virtual

User Data Types

For each event callback that is triggered, you can add user data by returning objects containing key-value pairs of different data types. Each user data type is an object containing properties of a specific data type.

Make sure the data type correctly matches the key-value pair. If you send the wrong key-value inside the userData object, such as adding a date key-value pair in a string data type, you will receive a generic error.

Data TypeDescriptionExample

userData

This data type is for setting one or more properties of type string. The value must be in a string, even if the value is set to a numeric value.
{
   user: "john_thompson",
   cart: "100.00"
};
JS

userDataLong

This data type is for setting one or more properties of type long and must be a numeric value without decimals.
{
    numberOfProducts: 17,
    numberOfSales: 1213
};
JS
userDataDoubleThis data type is for setting one or more properties of type double and must be a numeric value with decimals.
{
    monthlyVisitFrequency: 0.13333333,
    avgCustomerConversion: 0.0361922
};
JS

userDataBoolean

This data type is for setting one or more properties of type boolean.
{
    returnCustomer: true,
    subscriber: false
};
JS

userDataDate

This data type is for setting one or more properties of type date. The value must be the converted Epoch value of the date.
{
    epoch1: 1448675019877,
    epoch2: 1418475982737
};
JS

Syntax of User Data Objects

You add user data as objects for each page event to the JavaScript Agent configuration. The base page, Ajax, and virtual pages have the following corresponding user data objects:

  • PageView
  • Ajax
  • VPageView

The PageViewAjax, and VPageView objects have slightly different syntaxes. UserPageName is only available for PageView and VPageView, and not for Ajax and Error.

userEventInfo: {
			"PageView": function(context) {
                return {
                    userPageName: "String"
                    userData: {
                        userDataOne: "String",
                        userDataTwo: "String",
						someKey: "String"
                    },
                    userDataLong: {
                        longPropertyOne: Numeral,
                        longPropertyTwo: Numeral,
						someKey: Numeral
                    },
                    userDataDouble: {
                        userDataDoubleOne: Decimal,
                        userDataDoubleTwo: Decimal,
						someKey: Numeral
                    },
                    userDataBoolean: {
                        userDataBooleanOne: Boolean,
                        userDataBooleanTwo: Boolean,
						someKey: Boolean
                    },
                    userDataDate: {
                        epoch1: Epoch numeral,
                        epoch2: Epoch numeral,
                        currentTime: ((new Date()).getTime()),
                        someKey: ((new Date()).getTime())
                    }
                }
			}

			"Ajax" : function(context) {
                if (context.method.toLowerCase() === 'post') {
                    var anyKey = "String";
                } else {
                    variableName = "String";
                }
                return {
                    userData: {
                        userDataOne: "String",
                        userDataTwo: "String"
						variableName: VariableName
                    },
                    userDataLong: {
                        longPropertyOne: Numeral,
                        longPropertyTwo: Numeral
                    },
                    userDataDouble: {
                        userDataDoubleOne: Decimal,
                        userDataDoubleTwo: Decimal
                    },
                    userDataBoolean: {
                        userDataBooleanOne: Boolean,
                        userDataBooleanTwo: Boolean
                    },
                    userDataDate: {
                        epoch1: Epoch numeral,
                        epoch2: Epoch numeral
                    }
                }
            },
            "VPageView": function(context) {
                return {
					userPageName: "String",
                    userData: {
                        userDataOne: "String",
                        userDataTwo: "String"
                    },
                    userDataLong: {
                        longPropertyOne: Numeral,
                        longPropertyTwo: Numeral
                    },
                    userDataDouble: {
                        userDataDoubleOne: Decimal,
                        userDataDoubleTwo: Decimal
                    },
                    userDataBoolean: {
                        userDataBooleanOne: Boolean,
                        userDataBooleanTwo: Boolean
                    },
                    userDataDate: {
                        epoch1: Epoch numeral,
                        epoch2: Epoch numeral
                    }
				}
			},
			"Error": function(context) {
                return {
                    userPageName: "String",
                    userData: {
                        username: "String",
                        cart: "String"
                    },
                    userDataLong: {
                        longExample1: Numeral,
                        longExample2: Numeral
                    },
                    userDataDouble: {
                        doubleExample1: Decimal,
                        doubleExample2: Decimal
                    },
                    userDataBoolean: {
                        booleanExample1: Boolean,
                        booleanExample2: Boolean
                    },
                    userDataDate: {
                        epoch1: Epoch numeral,
                        epoch2: Epoch numeral
                    }
                }
            }
        }
    };
JS
userEventInfo: {
			"PageView": function(context) {
                return {
                    userPageName: "UserEventInfoTestPage",
                    userData: {
                        username: "basepage_user",
                        cart: "100.00",
                        someKey: "111222333444555"
                    },
                    userDataLong: {
    					numberOfProducts: 17,
    					numberOfSales: 1213
                        someKey: 111222333444555
                    },
                    userDataDouble: {
                        monthlyVisitFrequency: 0.13333333,
                        avgCustomerConversion: 0.0361922
                        someKey: 111222333444555.666
                    },
                    userDataBoolean: {
                        returnCustomer: true,
    					subscriber: false
                        someKey: true
                    },
                    userDataDate: {
                        checkoutTime: 1441751614436,
                        currentTime: ((new Date()).getTime()),
                        someKey: ((new Date()).getTime())
                    }
                }
			"Ajax" : function(context) {
                var property = '';
					if (context.method.toLowerCase() === 'post') {
                    	property = "Could be doing something";
                		} 
					else {
                    	property = "Idempotent, hopefully";
                }
                return {
                    userData: {
                        username: "xhr_user",
                        cart: "218.50",
                        property: property
                    },
                    userDataLong: {
                        numberOfProducts: 17,
    					numberOfSales: 1213
                    },
                    userDataDouble: {
                        monthlyVisitFrequency: 0.13333333,
                        avgCustomerConversion: 0.0361922
                    },
                    userDataBoolean: {
                        returnCustomer: true,
    					subscriber: false
                    },
                    userDataDate: {
                        checkoutTime: 1441751614436,
                        currentTime: ((new Date()).getTime()),
                    }
                }
            },
            "VPageView": function(context) {
                return {
                    userData: {
                        username: "virtualpage_user",
                        cart: "200.00"
                    },
                    userDataLong: {
                        numberOfProducts: 17,
    					numberOfSales: 1213
                    },
                    userDataDouble: {
                        monthlyVisitFrequency: 0.13333333,
                        avgCustomerConversion: 0.0361922
                    },
                    userDataBoolean: {
                        returnCustomer: true,
    					subscriber: false
                    },
                    userDataDate: {
                        checkoutTime: 1441751614436,
                        currentTime: ((new Date()).getTime()),
                    }
                }
            },
			"Error": function(context) {
                return {
                    userPageName: "UserEventInfoTestPage",
                    userData: {
                        username: "automated_tester",
                        cart: "100.00"
                    },
                    userDataLong: {
                        longExample1: 129414,
                        longExample2: 524546
                    },
                    userDataDouble: {
                        doubleExample1: 5982.612575313542,
                        doubleExample2: 5084.016120518092
                    },
                    userDataBoolean: {
                        booleanExample1: true,
                        booleanExample2: false
                    },
                    userDataDate: {
                        epoch1: 1441751614436,
                        epoch2: 1441751614438
                    }
                }
            }
        }
    };
JS


Capture Ajax Data for Setting User Data

When setting user data for the Ajax event, the JavaScript Agent configuration provides a context object that has properties for the HTTP method, the request URL, and the request payload of the Ajax request. You can use this information to set values for the user data configuration object.

The JavaScript Agent does not intercept or expose the response from the Ajax request. Thus, you can only include the request information (HTTP method, request URL, and request payload) in the user data that you report.

Ajax Context Object

To access the URL and HTTP method of the Ajax request, you can simply access the method and url properties of the context object. For the request payload of the Ajax request, you need to first match the payload parameters (HTTP method or Ajax URL) to access the data property. See Match the Ajax Payload Parameters to learn how to define the filters to match the payload parameters.

The context object has the following properties:

PropertyDescriptionData TypeRequirement to Access Property
methodThe HTTP method used to make the Ajax request.stringXHR call
urlThe URL used to make the Ajax request. stringXHR call
dataThe request payload attached to the Ajax request.Any data type that can be passed as the body to xhr.send.
  • XHR call
  • XHR filter for the payload parameter

Match the Ajax Payload Parameters

To access the request payload, you need to use xhr.payloadParams array to match the HTTP method and/or the Ajax URL. To match the Ajax URL, you can specify one or more patterns. To match the HTTP method, you include one or more objects specifying HTTP methods.

In the "Match HTTP Methods" example, the payloadParams array is used to match the HTTP methods "POST" and "GET". In the "Matching URLs" example, the payloadParams array is used to match URLs with the following string: '.*/xhr/uptime'.

<script type = 'text/javascript' charset = 'UTF-8' >
    window['adrum-config'] = {
        xhr: {
            payloadParams: [{
                method: 'POST'
            }, {
                method: 'GET'
            }]
        },
        ...
    }
JS
window['adrum-config'] = {
    xhr: {
        payloadParams: [{urls: [{pattern: '.*/xhr/uptime'}]}]
    },
    ...
}
JS

Ajax Payload Filter Examples

Conventional Ajax Requests

In the following examples, the data from a conventional Ajax request payload is used to set custom user data. For capturing the request payload for Fetch API calls, see Ajax Requests Using the Fetch API.

This example only sets the user data configuration objects with data from the Ajax request payload if the HTTP method is POST.

<script type='text/javascript' charset='UTF-8'>   
    window['adrum-config'] = {
        xhr: {
            payloadParams: [{method: 'POST'}]
        },
        userEventInfo: {
            "Ajax" : function(context) {
                if (context.data && context.data.indexOf("purchase") > -1) {
                    // The URLSearchParams API does not work on IE/Edge
                    var payload = new URLSearchParams(context.data);
                    return {
                        userData: {
                            username: payload.get("username"),
                            email: payload.get("email"),
                            phone: payload.get("phone")
                        },
                        userDataLong: {
                            customerId: Number(payload.get("customer_id"),
                            totalPurchases: Number(payload.get("total_purchases")
                        },
                        userDataDouble: {
                            purchaseTotal: Double(payload.get("total") 
                    },
                    userDataBoolean: {
                        discounted: Boolean(payload.get("discounted"),
                        vipMember: Boolean(payload.get("member")
                    },
                    userDataDate: {
                        purchaseTime: Date.now()
                    }
                }
            }
        }
    };
</script>
<script src='//cdn.appdynamics.com/adrum/adrum-latest.js' type='text/javascript' charset='UTF-8'></script>
JS

This example only sets the user data configuration objects with data from the Ajax request payload if the Ajax URL matches the pattern ".*/transaction". For example, the URL http://example.com/transaction would match the pattern and cause the user data configuration to be set with data from the Ajax request payload.

<script type='text/javascript' charset='UTF-8'>
    window['adrum-config'] = {
        xhr: {
            payloadParams: [{urls: [{pattern: '.*/transaction'}]}]
        },
        userEventInfo: {
            "Ajax" : function(context) {
                if (context.data && (context.data.indexOf("username") > -1) && (context.data.indexOf("customer_id") > -1) && (customer.data.indexOf("phone") > -1)) {
                    // The URLSearchParams API does not work on IE/Edge
                    var payload = new URLSearchParams(context.data);
                    return {
                        userData: {
                            username: payload.get("username"),
                            email: payload.get("email"),
                            phone: payload.get("phone")
                        },
                        userDataLong: {
                            customerId: Number(payload.get("customer_id")
                            totalPurchases: Number(payload.get("total_purchases") || 0
                        },
                        userDataDouble: {
                            purchaseTotal: Number(payload.get("total") || 0
                        },
                        userDataBoolean: {
                            discounted: Boolean(payload.get("discounted") || false,
                            vipMember: Boolean(payload.get("member") || false
                        },
                        userDataDate: {
                            purchaseTime: Date.now()
                        }
                   }
                }
            }
        };
    }
</script>
<script src='//cdn.appdynamics.com/adrum/adrum-latest.js' type='text/javascript' charset='UTF-8'></script>
JS

Ajax Requests Using the Fetch API

The example below demonstrates how to use the JavaScript Agent configuration to match the HTTP method, the request URL, and the request body for Ajax calls using the Fetch API. The Fetch API call is also provided to add context. The JavaScript Agent cannot access the request body, however, if you supply your own Request object to the fetch method.

This Fetch API example sets the from the Ajax request payload if the HTTP method is POST.

<script type='text/javascript' charset='UTF-8'>
    // Note: URLSearchParams() is not supported in IE/Edge
    let queryParams = new URLSearchParams(window.location.search.substr(1));
    fetch('https://my-json-server.typicode.com/typicode/demo/posts', {
        method: 'post',
        body: queryParams.toString()
    }).then(function(response) {
        return response.json();
    }).then(function(data) {
        console.log('Posted content:', data.request_url);
    });
</script>
JS

This example only sets the user data configuration objects with data from the Ajax request payload if the HTTP method is POST and the Ajax URL matches the pattern ".*/posts".

<script type='text/javascript' charset='UTF-8'>
    window['adrum-config'] = {
      xhr: {
        payloadParams: [{method: 'POST'}, {urls: [{pattern: '.*/posts'}]}]
      },
      userEventInfo: {
        "Ajax": function (context) {
          var payload = null;
          if (context.data && (context.data.indexOf("id") > -1) && (context.data.indexOf("title") > -1)) {
            // The URLSearchParams API does not work on IE/Edge
            payload = new URLSearchParams(context.data).toString();
          } else if (context.data && context.data.indexOf("id") > -1) {
            // The URLSearchParams API does not work on IE/Edge
            var params = new URLSearchParams(context.data); 
            params.set("title", "Post for " + params.get("id"));
            payload = params.toString();
          } else {
            payload = "Payload is not available";
          }
          return {
            userData: {
              username: "xhr_user",
              cart: "218.50",
              payload: payload
            }
          }
        }
      }
    };
</script>
<script src='//cdn.appdynamics.com/adrum/adrum-latest.js' type='text/javascript' charset='UTF-8'></script>
JS

Custom User Data Examples

The following examples show you how to set custom data for different page types and using the different methods:

Setting User Data with Function Pointers

The example below assigns a value to the userPageName property of the PageView object by executing the function extractUserData, which extracts data from the cookies.

< script type = 'text/javascript'
charset = 'UTF-8' >
	(function (config) {
		(function (info) {
			info.PageView = extractUserData;
		})(config.userEventInfo || (config.userEventInfo = {}))
	})(window['adrum-config'] || (window['adrum-config'] = {}));

function extractUserData() {
	var cookies = document.cookie.split(';');
	for (var i = 0; i < cookies.length; i++) {
		var cookie = cookies[i].trim();
		if (cookie.indexOf("role=") === 0) {
			var role = cookie.substring(5);
		}
	}
	return {
		userPageName: role
	};
} <
/script> <
script src = '//cdn.appdynamics.com/adrum/adrum-latest.js'
type = 'text/javascript'
charset = 'UTF-8' > < /script>
JS

Setting User Data with an Anonymous Function

You can also use anonymous functions that return an object as shown in this example for setting user data for virtual pages.

< script type = 'text/javascript'
charset = 'UTF-8' >
	(function (config) {
		(function (info) {
			info.VPageView = function () {
				return {
					userData: {
						version: window.location.href.split("/")[4],
						space: space(),
						email: getEmail()
					},
					userPageName: $('title').get(0).text,
					userDataDate: {
						currentTime: ((new Date()).getTime())
					},
					userDataBoolean: {
						watchingPage: watchingPage()
					}
				}
			}
		})(config.userEventInfo || (config.userEventInfo = {}))
	})(window['adrum-config'] || (window['adrum-config'] = {})); <
/script> <
script src = '//cdn.appdynamics.com/adrum/adrum-latest.js'
type = 'text/javascript'
charset = 'UTF-8' > < /script>
XML

Setting User Data with Multiple Methods

You might also want to use a combination of literal values, named and anonymous functions as this example does for setting user data for the Ajax event. Note, the context object is only available for Ajax events, and this object has the properties data (stores the request payload), method (HTTP method used to make Ajax request), and url (the Ajax request URL).  

<script type='text/javascript' charset='UTF-8'>
    (function(config){
        (function(info) {
            info.Ajax = function(context) { 
                return { 
                    userPageName: $('title').get(0).text,
                    userData: extractUserData(context)
                    userDataBoolean: {
				        "visited": true
                    }
                }
            };
        })(config.userEventInfo || (config.userEventInfo = {}))
   })(window['adrum-config'] || (window['adrum-config'] = {}));
 
   function extractUserData(context) { 
        var cookies = document.cookie.split(';');
        for (var i = 0; i < cookies.length; i++) {
            var cookie = cookies[i].trim();
            if (cookie.indexOf("email=") === 0) {
                var role = cookie.substring(5);
            }
        }
        return {
            role: role,
            url: context.url,
            method: context.method
        };
    }
</script>
<script src='//cdn.appdynamics.com/adrum/adrum-latest.js' type='text/javascript' charset='UTF-8'></script>
XML