Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FIX: Avoid double-counting pageviews when navigating with loading spinner #23107

Merged
merged 1 commit into from Aug 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -65,10 +65,17 @@ export default {
},

handleRouteWillChange(transition) {
// will be null on initial boot transition, which is already tracked as a pageview via the HTML request
if (transition.from) {
trackNextAjaxAsPageview();
// transition.from will be null on initial boot transition, which is already tracked as a pageview via the HTML request
if (!transition.from) {
return;
}

// Ignore intermediate transitions (e.g. loading substates)
if (transition.isIntermediate) {
return;
}
Comment on lines +73 to +76
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice, I should maybe use this in chat at various places 🤔


trackNextAjaxAsPageview();
},

teardown() {
Expand Down
140 changes: 113 additions & 27 deletions app/assets/javascripts/discourse/tests/acceptance/page-tracking-test.js
Expand Up @@ -2,38 +2,124 @@ import { acceptance } from "discourse/tests/helpers/qunit-helpers";
import { click, visit } from "@ember/test-helpers";
import { test } from "qunit";
import pretender from "discourse/tests/helpers/create-pretender";
import { getOwner } from "@ember/application";
import { ajax } from "discourse/lib/ajax";

const trackViewHeaderName = "Discourse-Track-View";

function setupPretender(server, helper) {
server.get("/fake-analytics-endpoint", (request) => {
if (request.requestHeaders[trackViewHeaderName]) {
throw "Fake analytics endpoint was called with track-view header";
}
return helper.response({});
});
}

function setupFakeAnalytics(ref) {
getOwner(ref)
.lookup("service:router")
.on("routeDidChange", () => ajax("/fake-analytics-endpoint"));
}

function assertRequests({ assert, tracked, untracked, message }) {
let trackedCount = 0,
untrackedCount = 0;

const requests = pretender.handledRequests;
requests.forEach((request) => {
if (request.requestHeaders[trackViewHeaderName]) {
trackedCount++;
} else {
untrackedCount++;
}
});

assert.strictEqual(trackedCount, tracked, `${message} (tracked)`);
assert.strictEqual(untrackedCount, untracked, `${message} (untracked)`);

pretender.handledRequests = [];
}

acceptance("Page tracking - loading slider", function (needs) {
needs.user();
needs.pretender(setupPretender);

test("sets the discourse-track-view header correctly", async function (assert) {
setupFakeAnalytics(this);

assertRequests({
assert,
tracked: 0,
untracked: 0,
message: "no requests before app boot",
});

await visit("/");
assertRequests({
assert,
tracked: 0,
untracked: 2,
message: "no ajax tracked for initial page load",
});

await click("#site-logo");
assertRequests({
assert,
tracked: 1,
untracked: 1,
message: "tracked one pageview for reloading latest",
});

await visit("/t/-/280");
assertRequests({
assert,
tracked: 1,
untracked: 1,
message: "tracked one pageview for navigating to topic",
});
});
});

acceptance("Page tracking - loading spinner", function (needs) {
needs.user();
needs.pretender(setupPretender);
needs.settings({
page_loading_indicator: "spinner",
});

acceptance("Page tracking", function () {
test("sets the discourse-track-view header correctly", async function (assert) {
const trackViewHeaderName = "Discourse-Track-View";
assert.strictEqual(
pretender.handledRequests.length,
0,
"no requests logged before app boot"
);
setupFakeAnalytics(this);

assertRequests({
assert,
tracked: 0,
untracked: 0,
message: "no requests before app boot",
});

await visit("/");
assert.strictEqual(
pretender.handledRequests.length,
1,
"one request logged during app boot"
);
assert.strictEqual(
pretender.handledRequests[0].requestHeaders[trackViewHeaderName],
undefined,
"does not track view for ajax before a transition has taken place"
);
assertRequests({
assert,
tracked: 0,
untracked: 2,
message: "no ajax tracked for initial page load",
});

await click("#site-logo");
assert.strictEqual(
pretender.handledRequests.length,
2,
"second request logged during next transition"
);
assert.strictEqual(
pretender.handledRequests[1].requestHeaders[trackViewHeaderName],
"true",
"sends track-view header for subsequent requests"
);
assertRequests({
assert,
tracked: 1,
untracked: 1,
message: "tracked one pageview for reloading latest",
});

await visit("/t/-/280");
assertRequests({
assert,
tracked: 1,
untracked: 1,
message: "tracked one pageview for navigating to topic",
});
});
});