Skip to content

Commit

Permalink
Add self tracking capabilities
Browse files Browse the repository at this point in the history
  • Loading branch information
ar2rsawseen committed Jan 17, 2025
1 parent 067f92e commit 7f07305
Show file tree
Hide file tree
Showing 4 changed files with 171 additions and 127 deletions.
3 changes: 1 addition & 2 deletions frontend/express/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -116,8 +116,8 @@ plugins.setConfigs("frontend", {
session_timeout: 30,
use_google: true,
code: true,
google_maps_api_key: "",
offline_mode: false,
self_tracking: "",
});

if (!plugins.isPluginEnabled('tracker')) {
Expand All @@ -137,7 +137,6 @@ plugins.setUserConfigs("frontend", {
session_timeout: false,
use_google: false,
code: false,
google_maps_api_key: ""
});

plugins.setConfigs("security", {
Expand Down
280 changes: 156 additions & 124 deletions frontend/express/views/dashboard.html
Original file line number Diff line number Diff line change
Expand Up @@ -1886,148 +1886,180 @@ <h4><a href="#/analytics/events/key/{{encodeURIComponent this.name}}">{{this.nam

<script>Backbone.history.start();</script>
<% if (!offline_mode) { %>
<% if (!track || track == "GA" && member['global_admin'] || track == "noneGA" && !member['global_admin']) { %>
<!--Countly script-->
<script type='text/javascript' src='<%- cdn %>sdk/web/countly.min.js?<%= countlyVersion %>'></script>
<script type='text/javascript'>

Countly.getViewName = function(){
var view = "/dashboard#";
var fragment = Backbone.history.getFragment();
var parts = fragment.split("/");
if (fragment.indexOf("/analytics/retention/") === 0) {
parts[4] = ":event";
}
if (fragment.indexOf("/attribution/") === 0) {
parts[2] = ":campaign_id";
}
for (var i = 1; i < parts.length; i++) {
if (/\d/.test(parts[i])) {
parts[i] = ":id";
}
if (parts[i][0] === "{") {
parts[i] = ":query";
}
<!--Countly script-->
<script type='text/javascript' src='<%- cdn %>sdk/web/countly.min.js?<%= countlyVersion %>'></script>
<script type='text/javascript'>

Countly.getViewName = function(){
var view = "/dashboard#";
var fragment = Backbone.history.getFragment();
var parts = fragment.split("/").slice(0, 3);
if (fragment.indexOf("/attribution/") === 0) {
parts[2] = ":campaign_id";
}
if (fragment.indexOf("/users/") === 0 && parts.length === 3) {
parts[2] = ":user_id";
}
for (var i = 1; i < parts.length; i++) {
if (/\d/.test(parts[i])) {
parts[i] = ":id";
}
return view + parts.join("/");
};

Countly.getViewUrl = function(){
var view = "/dashboard#";
var fragment = Backbone.history.getFragment();
var parts = fragment.split("/");
if (fragment.indexOf("/analytics/retention/") === 0) {
parts[4] = "[CLY]_session";
if (parts[i][0] === "{") {
parts[i] = ":query";
}
if (fragment.indexOf("/attribution/") === 0) {
parts[2] = "";
}
return view + parts.join("/");
};

Countly.getViewUrl = function(){
var view = "/dashboard#";
var fragment = Backbone.history.getFragment();
var parts = fragment.split("/").slice(0, 3);
if (fragment.indexOf("/attribution/") === 0) {
parts[2] = "";
}
if (fragment.indexOf("/users/") === 0 && parts.length === 3) {
parts[2] = "";
}
for (var i = 1; i < parts.length; i++) {
if (/\d/.test(parts[i])) {
parts[i] = "";
}
for (var i = 1; i < parts.length; i++) {
if (/\d/.test(parts[i])) {
parts[i] = "";
}
if (parts[i][0] === "{") {
parts[i] = "{}";
}
if (parts[i][0] === "{") {
parts[i] = "{}";
}
return view + parts.join("/");
};
}
return view + parts.join("/");
};

if (countlyGlobal.countly_tracking) {
var domain = countlyGlobal.countly_domain;
if (countlyGlobal.countly_tracking) {
var domain = countlyGlobal.countly_domain;

try {
// try to extract hostname from full domain url
var urlObj = new URL(domain);
domain = urlObj.hostname;
}
catch (_) {
// do nothing, domain from config will be used as is
}
try {
// try to extract hostname from full domain url
var urlObj = new URL(domain);
domain = urlObj.hostname;
}
catch (_) {
// do nothing, domain from config will be used as is
}

//initializing countly with params
Countly.init({
app_key: countlyGlobal.frontend_app,
url: countlyGlobal.frontend_server,
device_id: domain,
app_version: "<%= countlyVersion %>",
interval:1000
});
//initializing countly with params
Countly.init({
app_key: countlyGlobal.frontend_app,
url: countlyGlobal.frontend_server,
device_id: domain,
app_version: "<%= countlyVersion %>",
interval:1000
});

// if domain has changed since the last time it is saved as device id set the new domain as device id and merge it with the old domain
if (Countly.get_device_id() !== domain) {
Countly.change_id(domain, true);
}
// if domain has changed since the last time it is saved as device id set the new domain as device id and merge it with the old domain
if (Countly.get_device_id() !== domain) {
Countly.change_id(domain, true);
}

//track sessions automatically
Countly.track_sessions();

//track sessions automatically
Countly.track_sessions();
//track pageviews automatically
Countly.track_pageview(Countly.getViewName());

//track pageviews automatically
$(window).on('hashchange', function() {
Countly.track_pageview(Countly.getViewName());
});

//track any clicks to webpages automatically
Countly.track_clicks();

$(window).on('hashchange', function() {
Countly.track_pageview(Countly.getViewName());
//track javascript errors
Countly.track_errors();

//display in app messages
if (Countly.content.enterContentZone) {
Countly.content.enterContentZone();
}

if (Countly.report_trace && window.performance && window.performance.timing) {
$(window).on( "load", function(){
setTimeout(function(){
var trace = {
type: "device",
name: Countly.getViewName(),
stz: window.performance.timing.navigationStart,
etz: window.performance.timing.domContentLoadedEventEnd,
apm_metrics: {}
};
if (window.performance.timing.domLoading && window.performance.timing.navigationStart) {
trace.apm_metrics.first_paint = window.performance.timing.domLoading - window.performance.timing.navigationStart;
}
if (window.performance.timing.domContentLoadedEventStart && window.performance.timing.navigationStart) {
trace.apm_metrics.first_contentful_paint = window.performance.timing.domContentLoadedEventStart - window.performance.timing.navigationStart;
}
if (window.performance.timing.domInteractive && window.performance.timing.navigationStart) {
trace.apm_metrics.dom_interactive = window.performance.timing.domInteractive - window.performance.timing.navigationStart;
}
if (window.performance.timing.domContentLoadedEventEnd && window.performance.timing.domContentLoadedEventStart) {
trace.apm_metrics.dom_content_loaded_event_end = window.performance.timing.domContentLoadedEventEnd - window.performance.timing.domContentLoadedEventStart;
}
if (window.performance.timing.loadEventEnd && window.performance.timing.loadEventStart) {
trace.apm_metrics.load_event_end = window.performance.timing.loadEventEnd - window.performance.timing.loadEventStart;
}
if (Object.keys(trace.apm_metrics).length) {
Countly.report_trace(trace);
}
},1);
});
}

Countly.userData.set("lastServer", window.location.hostname);
Countly.userData.set("lastVersion", "<%= countlyVersion %>");
Countly.userData.set("lastEdition", "<%= countlyTypeTrack %>");
Countly.userData.set("isTrial", <%= countlyTrial %>);
Countly.userData.set("cpus", <%= cpus %>);
Countly.userData.push_unique("servers", window.location.hostname);
Countly.userData.push_unique("versions", "<%= countlyVersion %>");
Countly.userData.push_unique("editions", "<%= countlyTypeTrack %>");
Countly.userData.save();

//track any clicks to webpages automatically
Countly.track_clicks();
<% if (installed) { %>
Countly.add_event({
key:"INSTALL"
});
<% } %>
}

//track javascript errors
Countly.track_errors();
if (countlyGlobal.config.self_tracking) {
//initializing countly with params
var Countly2 = Countly.init({
app_key: countlyGlobal.config.self_tracking,
url: window.location.origin,
device_id: countlyGlobal.member.email,
app_version: "<%= countlyVersion %>",
interval:1000
});

//display in app messages
Countly.content.enterContentZone();

if (Countly.report_trace && window.performance && window.performance.timing) {
$(window).on( "load", function(){
setTimeout(function(){
var trace = {
type: "device",
name: Countly.getViewName(),
stz: window.performance.timing.navigationStart,
etz: window.performance.timing.domContentLoadedEventEnd,
apm_metrics: {}
};
if (window.performance.timing.domLoading && window.performance.timing.navigationStart) {
trace.apm_metrics.first_paint = window.performance.timing.domLoading - window.performance.timing.navigationStart;
}
if (window.performance.timing.domContentLoadedEventStart && window.performance.timing.navigationStart) {
trace.apm_metrics.first_contentful_paint = window.performance.timing.domContentLoadedEventStart - window.performance.timing.navigationStart;
}
if (window.performance.timing.domInteractive && window.performance.timing.navigationStart) {
trace.apm_metrics.dom_interactive = window.performance.timing.domInteractive - window.performance.timing.navigationStart;
}
if (window.performance.timing.domContentLoadedEventEnd && window.performance.timing.domContentLoadedEventStart) {
trace.apm_metrics.dom_content_loaded_event_end = window.performance.timing.domContentLoadedEventEnd - window.performance.timing.domContentLoadedEventStart;
}
if (window.performance.timing.loadEventEnd && window.performance.timing.loadEventStart) {
trace.apm_metrics.load_event_end = window.performance.timing.loadEventEnd - window.performance.timing.loadEventStart;
}
if (Object.keys(trace.apm_metrics).length) {
Countly.report_trace(trace);
}
},1);
});
}
//track sessions automatically
Countly2.track_sessions();

Countly.userData.set("lastServer", window.location.hostname);
Countly.userData.set("lastVersion", "<%= countlyVersion %>");
Countly.userData.set("lastEdition", "<%= countlyTypeTrack %>");
Countly.userData.set("isTrial", <%= countlyTrial %>);
Countly.userData.set("cpus", <%= cpus %>);
Countly.userData.push_unique("servers", window.location.hostname);
Countly.userData.push_unique("versions", "<%= countlyVersion %>");
Countly.userData.push_unique("editions", "<%= countlyTypeTrack %>");
Countly.userData.save();

<% if (installed) { %>
Countly.add_event({
key:"INSTALL"
});
<% } %>
//track pageviews automatically
Countly2.track_pageview(Countly.getViewName());

$(window).on('hashchange', function() {
Countly2.track_pageview(Countly.getViewName());
});

//display in app messages
if (Countly2.content.enterContentZone) {
Countly2.content.enterContentZone();
}
</script>
<% } %>

Countly2.user_details({
"name": countlyGlobal.member.full_name || "",
"username": countlyGlobal.member.username || "",
"email": countlyGlobal.member.email
});
}
</script>
<% } %>
<script type='text/javascript'>
app.recordEvent = function (event) {
Expand Down
11 changes: 11 additions & 0 deletions plugins/plugins/frontend/public/javascripts/countly.views.js
Original file line number Diff line number Diff line change
Expand Up @@ -1170,6 +1170,17 @@
}
});

var appList = [{value: "", label: jQuery.i18n.map["configs.frontend-self_tracking.none"]}];
for (var a in countlyGlobal.apps) {
appList.push({value: countlyGlobal.apps[a].key, label: countlyGlobal.apps[a].name});
}

app.configurationsView.registerInput("frontend.self_tracking", {
input: "el-select",
attrs: {},
list: appList
});

app.configurationsView.registerStructure("api", {
description: "configs.api.description",
groups: [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ configs.no-theme = Default Theme
configs.frontend-code = Show Code Generator for SDK integration
configs.frontend-offline_mode = Offline mode
configs.frontend-countly_tracking = Countly
configs.frontend-self_tracking = Self tracking using Countly
configs.frontend-self_tracking.none = -- Not tracked --
configs.security-login_tries = Allowed login attempts
configs.security-login_wait = Incorrect login block time increment
configs.security-dashboard_additional_headers = Additional Dashboard HTTP Response headers
Expand Down Expand Up @@ -175,7 +177,7 @@ configs.help.frontend-countly_tracking = When enabled, Countly will be activated
configs.help.frontend-production = Initial load of dashboard should be faster, due to smaller files and smaller file amount, but when developing a plugin, you need to regenerate them to see changes
configs.help.frontend-theme = Selected theme will be available server-wide, for all apps and users
configs.help.frontend-session_timeout = User will be forced to logout after session timeout (in minutes) of inactivity. If you want to disable force logout, set to 0.
configs.help.frontend-google_maps_api_key = Google requires an API key for Geocharts visualization used in views such as Overview and Analytics > Countries. Provide your API key to use this visualization without any limitations.<br/><a href="https://developers.google.com/maps/documentation/javascript/get-api-key">Learn how to get your API key.</a>
configs.help.frontend-self_tracking = If you want to track usage of this server and users that are using the dashboard, select an app where to collect this data. Make sure to create a new app specifically for this purpose, or else you would merge collected data with existing. Data will only be stored on this server and will not be sent anywhere else. By selecting an app, you will enabling tracking of this server and it will count towards your datapoint quota. The scale of datapoints will depend on your user count and often usage of this dashboard.
configs.help.security-login_tries = Account will be blocked for some time after provided number of incorrect login attempts. See below for time increments.
configs.help.security-login_wait = Incremental period of time account is blocked after provided number of incorrect login attempts (in seconds)
configs.help.security-password_rotation = Amount of previous passwords user should not be able to reuse
Expand Down

0 comments on commit 7f07305

Please sign in to comment.