User Activity Tracking in Power Pages using Azure Application Insights
π User Activity Tracking in Power Pages using Azure Application Insights
π Introduction
In today's enterprise applications, understanding how users interact with your system is extremely important. It helps organizations improve user experience, monitor engagement, and make better business decisions.
However, Power Pages does not provide detailed user tracking capabilities out of the box. We cannot directly know:
- Who logged into the portal
- Which pages they visited
- How much time they spent
- What their complete journey looks like
To solve this problem, we can integrate Azure Application Insights, which allows us to capture and analyze user behavior in real time.
In this blog, we will build a complete user activity tracking system from scratch, which captures every important user interaction.
π― What We Will Achieve
- User Login & Logout
- Page navigation
- Form submissions
- Time spent on each page
- Complete user journey
π§° Prerequisites
Before starting, ensure you have:
- βA working Power Pages portal
- βAn active Azure subscription
- βAn Application Insights resource
- βBasic understanding of JavaScript
βοΈ Step 1: Create Application Insights
Azure Application Insights is used to collect and store telemetry data from your application.
Steps:
- 1 Go to Azure Portal
- 2 Search for Application Insights
- 3 Click Create β fill in: Name, Resource Group, Region
- 4 Click Review + Create
Important
After creation, go to Overview and copy the Connection String. This is used to connect your portal to Azure.
π Step 2: Add Script to Power Pages
Navigation:
Power Pages βΊ Edit Portal βΊ Web Templates βΊ HeaderWhy Header?
Because it ensures tracking works on every page automatically.
JavaScript Β· Header Web Template/* ββ Azure Application Insights SDK ββ */
<script src="https://js.monitor.azure.com/scripts/b/ai.2.min.js"></script>
<script>
/* ββ INITIALIZE ββββββββββββββββββββββββ */
var appInsights = new Microsoft.ApplicationInsights.ApplicationInsights({
config: {
connectionString: "YOUR_CONNECTION_STRING",
enableAutoRouteTracking: true
}
});
appInsights.loadAppInsights();
/* ββ USER DETAILS ββββββββββββββββββββββ */
var userId = "{{ user.id }}";
var userName = "{{ user.fullname }}";
var userEmail = "{{ user.emailaddress1 }}";
if (userId) {
appInsights.setAuthenticatedUserContext(userId);
}
/* ββ PAGE VIEW βββββββββββββββββββββββββ */
appInsights.trackPageView({
name: document.title,
uri: window.location.href
});
/* ββ LOGIN TRACKING ββββββββββββββββββββ */
if (userId && !sessionStorage.getItem("loginTracked")) {
appInsights.trackEvent({
name: "User_SignIn",
properties: {
userId: userId, userName: userName, userEmail: userEmail,
page: window.location.pathname, time: new Date().toISOString()
}
});
sessionStorage.setItem("loginTracked", "true");
}
/* ββ LOGOUT TRACKING βββββββββββββββββββ */
window.addEventListener("beforeunload", function () {
if (userId && sessionStorage.getItem("loginTracked")) {
appInsights.trackEvent({
name: "User_SignOut",
properties: {
userId: userId, userName: userName, userEmail: userEmail,
page: window.location.pathname, time: new Date().toISOString()
}
});
sessionStorage.removeItem("loginTracked");
}
});
/* ββ CLICK TRACKING ββββββββββββββββββββ */
document.addEventListener("click", function (e) {
var el = e.target;
while (el && el.tagName !== "A" && el.tagName !== "BUTTON") {
el = el.parentElement;
}
if (!el) return;
appInsights.trackEvent({
name: "User_Click",
properties: {
elementType: el.tagName, text: (el.innerText || "").trim(),
url: el.href || "", page: window.location.pathname,
userId: userId, userName: userName, userEmail: userEmail,
time: new Date().toISOString()
}
});
});
/* ββ FORM SUBMIT βββββββββββββββββββββββ */
document.addEventListener("submit", function (e) {
appInsights.trackEvent({
name: "Form_Submit",
properties: {
formName: e.target.name || "unknown", page: window.location.pathname,
userId: userId, userName: userName, userEmail: userEmail,
time: new Date().toISOString()
}
});
});
/* ββ INPUT FIELD TRACKING ββββββββββββββ */
document.addEventListener("change", function (e) {
var field = e.target;
if (field.tagName === "INPUT" || field.tagName === "SELECT" || field.tagName === "TEXTAREA") {
appInsights.trackEvent({
name: "Field_Interaction",
properties: {
fieldName: field.name || field.id, page: window.location.pathname,
userId: userId, userName: userName, userEmail: userEmail,
time: new Date().toISOString()
}
});
}
});
/* ββ SCROLL TRACKING βββββββββββββββββββ */
var scrollTracked = false;
window.addEventListener("scroll", function () {
if (!scrollTracked && window.scrollY > 300) {
appInsights.trackEvent({
name: "Scroll",
properties: {
scrollPosition: window.scrollY, page: window.location.pathname,
userId: userId, userName: userName, userEmail: userEmail,
time: new Date().toISOString()
}
});
scrollTracked = true;
}
});
/* ββ TIME SPENT ββββββββββββββββββββββββ */
var startTime = new Date();
window.addEventListener("beforeunload", function () {
var duration = (new Date() - startTime) / 1000;
appInsights.trackEvent({
name: "Time_Spent",
properties: {
seconds: duration, page: window.location.pathname,
userId: userId, userName: userName, userEmail: userEmail
}
});
});
/* ββ ERROR TRACKING ββββββββββββββββββββ */
window.onerror = function (message, source, lineno, colno, error) {
appInsights.trackException({
exception: error || new Error(message),
properties: {
source: source, line: lineno, column: colno,
userId: userId, userName: userName, userEmail: userEmail
}
});
};
</script>
π§ Understanding the Code (Deep Explanation)
β Initialization
Connects your portal to Azure Application Insights using the connection string and loads the SDK.
β User Context
Captures logged-in user details using Power Pages Liquid variables (user.id, user.fullname, user.emailaddress1) and sets the authenticated user context.
β Page Tracking
Tracks every page visited by the user by sending a trackPageView event with the page title and URL.
π Login Tracking
Tracks user login once per session using sessionStorage to prevent duplicate events on page refresh.
πͺ Logout Tracking
Captures logout or tab close event using the browser's beforeunload event, giving accurate session end data.
π±οΈ Click Tracking
Tracks all clicks including menu items and buttons by bubbling up the DOM to find the nearest anchor or button element.
π Form Tracking
Tracks form submissions with the form name and current page path.
β±οΈ Time Spent Tracking
Calculates how long the user stays on a page in seconds by recording the start time and computing the difference on unload.
πΎ Step 4: Save and Sync
After adding the script:
- 1 Click Save
- 2 Click Sync
π Step 5: Hard Refresh
Press Ctrl + Shift + R β this ensures the latest script loads and the browser cache is cleared.
π§ͺ Step 6: Testing (Very Important)
β Test Login
- 1Logout
-
2Login again and verify
User_SignInevent appears in Azure
β Test Clicks
- 1Click menu items
- 2Click buttons
β Test Form Submit
Submit any form on the portal and verify the Form_Submit event is recorded.
β Test Time Tracking
- 1Stay on a page for 20β30 seconds
- 2Navigate to another page
β Test Logout
Click logout and verify User_SignOut is captured in Azure Logs.
π Step 7: Analyze Data in Azure
Navigate to: Azure β Application Insights β Logs
πΉ User Login Query
KQLcustomEvents | where name == "User_SignIn" | project timestamp, userName, userEmail
πΉ User Activity Query
KQLcustomEvents | project timestamp, name, customDimensions | order by timestamp desc
πΉ Time Spent Query
KQLcustomEvents | where name == "Time_Spent" | summarize totalTime = sum(todouble(customDimensions.seconds))
π₯ What We Achieved
After implementing this solution, we successfully built:
- βComplete user tracking system
- βReal-time activity monitoring
- βPage-level engagement tracking
- βFull user journey visibility
π‘ Real-World Use Cases
- Analyze user behavior
- Identify popular pages
- Improve user experience
- Track engagement
- Debug issues
π Conclusion
By integrating Power Pages with Azure Application Insights, we can transform a simple portal into a powerful analytics platform.
Instead of guessing user behavior, we now have real data to make informed decisions.