diff --git a/src/plugins/docusaurus-plugin-segment/index.js b/src/plugins/docusaurus-plugin-segment/index.js index 5ee41b4d36..1642c001f1 100644 --- a/src/plugins/docusaurus-plugin-segment/index.js +++ b/src/plugins/docusaurus-plugin-segment/index.js @@ -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() { diff --git a/src/plugins/docusaurus-plugin-segment/linkTracking.js b/src/plugins/docusaurus-plugin-segment/linkTracking.js new file mode 100644 index 0000000000..29ea4f15b5 --- /dev/null +++ b/src/plugins/docusaurus-plugin-segment/linkTracking.js @@ -0,0 +1,71 @@ +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 + * + * Each entry has a `test(url)` predicate and an `element` label — a human-readable identifier + * for the clicked UI element, sent as the `element` property in the Segment "Clicked" event. + * Individual links can also opt in via a `data-tracking-id` attribute, which takes precedence. + * + * @example + * { test: (url) => url.hostname === 'trust.apify.com', element: 'trust-center-link' } + */ +const LINK_TRACKERS = [ + { + test: (url) => url.hostname === 'trust.apify.com', + element: 'trust-center-link', + }, + // 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)); + const dataId = anchor.dataset.trackingId; // reads data-tracking-id attribute + + if (!tracker && !dataId) return; + + const isApifyDomain = /(^|\.)apify\.com$/.test(url.hostname); + + window.analytics.track('Clicked', { + app: 'docs', + element: dataId ?? 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;