// ==UserScript== // @name Dynatrace Heatmap // @namespace Dynatrace // @version 1 // @description Heat map for Dynatrace // @author You // @require https://ajax.googleapis.com/ajax/libs/jquery/2.2.2/jquery.min.js // @require https://github.com/pa7/heatmap.js/raw/master/build/heatmap.js // @resource hmDialog https://raw.githubusercontent.com/Dynatrace/Dynatrace-UEM-PureLytics-Heatmap/master/heatmap-dialog.html // @grant GM.xmlHttpRequest // @grant GM_getResourceText // @connect * //Add the URL of the website where you want to display the Heatmap // @match // ==/UserScript== // change the defaults here: var hmUrl = "XX"; var hmUser = "XX"; var hmPass = "XX"; var hmTimeframe = 14; var bucketSize = 1; //optimization for creating points in groups instead of 1 at a time var debugLog = 0; // Set to 1 to enable console logs, 0 to diable logging var allClicks = "_type:useraction AND data.source.url: \\\"" + window.location + "\\\""; function createJSONQuery(query, durationms) { dt_log("createJSONQuery"); var data = '{\ "query": {\ "bool": {\ "must": [\ { "range": {\ "data.startTime": {\ "gte": ' + (new Date().getTime() - durationms) + ',\ "lte": ' + new Date().getTime() + '\ }\ }\ },\ { "query_string": {\ "query": "' + query + '",\ "analyze_wildcard": true }\ }\ ]\ }\ },\ "size": 0,\ "aggs": {\ "NAME": {\ "terms": {\ "field": "data.prettyName",\ "size": 200\ }\ }\ }\ }'; dt_log(data); return data; } function dt_log(msg) { if (debugLog) console.log(msg); } function drawHeatmap(links, showHidden) { // minimal heatmap instance configuration var heatmapInstance = h337.create({ // only container is required, the rest will be defaults container: document.querySelector('#heatmap-container') }); // now generate some random data var points = []; var max = 0; for (var i in links) { var currentLink = i.split("'").join("\\'"); // escape "'" otherwise the selector wont work var elems = []; dt_log("Current Link: " + currentLink); try { elems = $("a:contains('" + currentLink + "'), input[value='" + currentLink + "']"); } catch (e) { console.log(e); } dt_log("-- After contains"); if (elems.length == 0) { $("#heatmap-statistics").append("Could not find " + i + " (" + links[i] + ")
"); //continue; } dt_log("-- Update Stats"); elems.each(function (index, elem) { dt_log("Elem offset top: " + $(elem).offset().top + " left: " + $(elem).offset().left); var visible = $(elem).is(":visible"); dt_log("-- Checking visibility: " + elem); var offsetVisible = ($(elem).offsetParent().width() > $(elem).offset().left && $(elem).offsetParent().height() > $(elem).offset().top); dt_log("-- Checking offset visibility"); if (showHidden || (visible && offsetVisible)) { dt_log("-- In if statement: " + links[i]); var val = links[i] + 800; // add an offset to make all links visible max = Math.max(max, val); for (var j = 0; j < links[i]; j=j+bucketSize) { var point = { x: $(elem).offset().left + Math.floor(Math.random() * $(elem).width()), y: $(elem).offset().top + Math.floor(Math.random() * $(elem).height()), value: val }; for (var k = 0; k= 0; }; }); function downloadClickData(searchUrl, user, pass, query, timeframeDays, showHidden) { $("#heatmap-spinner").fadeIn(200).show(); $("#heatmap-container").empty().show(); $("#heatmap-statistics").empty().show(); $("#hmDialog").hide(); //alert ("Starting request"); var LINK_REGEX = /click on \"(.*)\"/g; GM.xmlHttpRequest( { method: "POST", url: searchUrl, user: user, password: pass, data: createJSONQuery(query, 1000*60*60*24*timeframeDays), headers: { "kbn-version": "5.0", // set kibana version - an apache proxy change can get rid of this "Content-Type": "text/json" }, onload: function (response) { var data = JSON.parse(response.responseText); var links = {}; var clicks = 0; var otherActions = 0; var topClick = ""; var topClickCount = 0; for (var i=0; i < data.aggregations.NAME.buckets.length; ++i) { var link = LINK_REGEX.exec(data.aggregations.NAME.buckets[i].key); var count = data.aggregations.NAME.buckets[i].doc_count; if (link) { clicks+=count; if (topClickCount < count) { topClickCount = count; topClick = link[1]; } links[link[1]] = count; } else { otherActions += count; } } $("#heatmap-statistics").append("Downloaded top " + data.aggregations.NAME.buckets.length + " user actions
"); $("#heatmap-statistics").append("=> " + clicks + " clicks
"); $("#heatmap-statistics").append("=> " + otherActions + " actions (page loads, ...)
"); $("#heatmap-statistics").append("Top click: " + topClick + "(" + topClickCount + ")
"); dt_log("Before Drawing Heatmap: " + JSON.stringify(links)); drawHeatmap(links, showHidden); $("#heatmap-spinner").hide(); }, onerror: function (response) { dt_log("Error: " + response); $("#heatmap-spinner").hide(); }, onabort: function (response) { dt_log("Aborted: " + response); $("#heatmap-spinner").hide(); }, ontimeout: function (response) { dt_log("Timeout: " + response); $("#heatmap-spinner").hide(); } }); } // DOM $("body").append(""); $("body").append(""); $("body").append(""); $("body").append(GM_getResourceText("hmDialog")); // Event handlers $("#hmClose").on("click", function() { $("#hmDialog").hide(); }); $("#hmQueryShortcuts").on("change", function() { $("#hmQuery").val(allClicks + " " + $("#hmQueryShortcuts").val()); }); $("#hmGenerateHeatmap").on("click", function() { var searchUrl = $("#hmUrl").val(); var user = $("#hmUser").val(); var pass = $("#hmPass").val(); var query = $("#hmQuery").val(); var timeframeDays = parseInt($("#hmTimeframe").val()); var showHidden = !$("#hmVisible").is(':checked'); downloadClickData(searchUrl, user, pass, query, timeframeDays, showHidden); }); $("#heatmap-container").on("click", function() { $("#heatmap-container").hide(); $("#heatmap-statistics").hide(); $("#hmDialog").show(); }); $("#heatmap-statistics").on("click", function() { $("#heatmap-statistics").hide(); }); // Initialize defaults $("#hmUrl").val(hmUrl); $("#hmUser").val(hmUser); $("#hmPass").val(hmPass); $("#hmTimeframe").val(hmTimeframe); $("#hmQuery").val(allClicks); $("#hmQueryShortcuts").append(""); $("#hmQueryShortcuts").append(''); $("#hmQueryShortcuts").append(''); $("#hmQueryShortcuts").append(''); $("#hmQueryShortcuts").append(""); $("#hmQueryShortcuts").append(''); $("#hmQueryShortcuts").append(''); $("#hmQueryShortcuts").append(''); $("#hmQueryShortcuts").append(''); $("#hmQueryShortcuts").append(''); $("#hmQueryShortcuts").append(""); $("#hmQueryShortcuts").append('');