Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion src/plugins/docusaurus-plugin-segment/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@ module.exports = function (context, options) {
name: 'docusaurus-plugin-segment',

getClientModules() {
return [path.resolve(__dirname, './segment')];
return [
path.resolve(__dirname, './segment'),
path.resolve(__dirname, './linkTracking'),
];
},

injectHtmlTags() {
Expand Down
59 changes: 59 additions & 0 deletions src/plugins/docusaurus-plugin-segment/linkTracking.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import ExecutionEnvironment from '@docusaurus/ExecutionEnvironment';

// Opt-in link trackers. Currently limited to Trust Center to avoid Segment noise - see https://github.com/apify/apify-docs/issues/2409.
const LINK_TRACKERS = [
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Question: Haven't you considered to instead mark elements to track with dataset attribute? Like data-tracking-id or similar? I don't mind this approach but it might be more clear what is actually being tracked.

{
test: (url) => url.hostname === 'trust.apify.com',
element: 'trust-center-link',
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

nit: please add a comment explaining also the element field

},
// Examples for future opt-in:
// { test: (url) => !/(^|\.)apify\.com$/.test(url.hostname) } // all outbound
// { test: () => true } // all links
];

let installed = false;

function handleLinkClick(event) {
// auxclick fires for all non-primary buttons; only handle middle click (button === 1)
if (event.type === 'auxclick' && event.button !== 1) return;
if (process.env.NODE_ENV !== 'production' || !window.analytics) return;

const anchor = event.target.closest('a[href]');
if (!anchor) return;

let url;
try {
url = new URL(anchor.getAttribute('href'), window.location.href);
} catch {
return;
}
if (!/^https?:$/.test(url.protocol)) return;

const tracker = LINK_TRACKERS.find(({ test }) => test(url));
if (!tracker) return;

const isApifyDomain = /(^|\.)apify\.com$/.test(url.hostname);

window.analytics.track('Clicked', {
app: 'docs',
element: tracker.element ?? 'link',
button_text: anchor.textContent?.trim().slice(0, 200) || null,
href: url.href,
is_subdomain: isApifyDomain && url.hostname !== window.location.hostname,
is_outbound: !isApifyDomain,
});
}

function installLinkClickTracker() {
if (installed) return;
installed = true;

document.addEventListener('click', handleLinkClick, { capture: true });
document.addEventListener('auxclick', handleLinkClick, { capture: true });
}

export default ExecutionEnvironment.canUseDOM ? {
onRouteDidUpdate() {
installLinkClickTracker();
},
} : null;