docs: Configure Segment (#8996)

This commit is contained in:
Ronnie Miller 2025-07-10 21:39:19 -07:00 committed by GitHub
commit c38df91841
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 152 additions and 25 deletions

View file

@ -0,0 +1,15 @@
import ExecutionEnvironment from '@docusaurus/ExecutionEnvironment';
// Client module for tracking page views on route changes
export function onRouteDidUpdate({location, previousLocation}) {
// Only track page views in the browser and when the path actually changes
if (
ExecutionEnvironment.canUseDOM &&
previousLocation &&
location.pathname !== previousLocation.pathname &&
window.analytics &&
window.analytics.page
) {
window.analytics.page();
}
}

View file

@ -0,0 +1,81 @@
import ExecutionEnvironment from '@docusaurus/ExecutionEnvironment';
let isDataAttributeTrackingInitialized = false;
/**
* Automatic click tracking using data attributes for Docusaurus
*
* Usage: Add data-event and other data-* attributes to any clickable element.
* The tracker will automatically send events to Segment when clicked.
*
* Example in navbar config:
* {
* href: "https://github.com/langflow-ai/langflow",
* 'data-event': 'GitHub Link Clicked',
* 'data-source': 'navbar',
* 'data-category': 'social'
* }
*
* This will automatically call:
* window.analytics.track("GitHub Link Clicked", {
* source: "navbar",
* category: "social",
* url: "https://github.com/langflow-ai/langflow",
* page: "/current-page"
* })
*/
function initializeDataAttributeTracking() {
// Only run on client side and prevent duplicate initialization
if (!ExecutionEnvironment.canUseDOM || isDataAttributeTrackingInitialized) return;
const handleClick = (event) => {
const target = event.target;
const trackingElement = target.closest('[data-event]');
if (!trackingElement) return;
const eventName = trackingElement.dataset.event;
if (!eventName) return;
// Extract all data-* attributes (except data-event itself)
const properties = {};
Object.keys(trackingElement.dataset).forEach(key => {
if (key !== 'event') {
// Convert camelCase to snake_case for consistency
const snakeKey = key.replace(/([A-Z])/g, '_$1').toLowerCase();
properties[snakeKey] = trackingElement.dataset[key];
}
});
// Track the event
if (window.analytics && typeof window.analytics.track === 'function') {
window.analytics.track(eventName, properties);
} else {
console.warn('Analytics not available for tracking:', eventName, properties);
}
};
// Remove existing listener if it exists
document.removeEventListener('click', handleClick);
// Add the new listener
document.addEventListener('click', handleClick);
// Mark as initialized
isDataAttributeTrackingInitialized = true;
}
// Initialize on DOM ready
if (ExecutionEnvironment.canUseDOM) {
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', initializeDataAttributeTracking);
} else {
initializeDataAttributeTracking();
}
// Re-initialize on route changes for SPA navigation
window.addEventListener('popstate', () => {
setTimeout(initializeDataAttributeTracking, 100);
});
}

View file

@ -0,0 +1,40 @@
// Custom Docusaurus plugin to inject Segment analytics
function pluginSegment(context, options = {}) {
const isProd = process.env.NODE_ENV === "production" || options.allowedInDev;
const segmentPublicWriteKey = options.segmentPublicWriteKey;
if (!segmentPublicWriteKey) {
console.warn('Segment plugin: No write key provided. Analytics will not be initialized.');
return { name: 'docusaurus-plugin-segment' };
}
return {
name: 'docusaurus-plugin-segment',
getClientModules() {
return isProd ? [require.resolve('./analytics-page'), require.resolve('./data-attribute-tracking')] : [];
},
injectHtmlTags() {
if (!isProd) {
return {};
}
return {
headTags: [
{
tagName: 'script',
innerHTML: `
!function(){var i="analytics",analytics=window[i]=window[i]||[];if(!analytics.initialize)if(analytics.invoked)window.console&&console.error&&console.error("Segment snippet included twice.");else{analytics.invoked=!0;analytics.methods=["trackSubmit","trackClick","trackLink","trackForm","pageview","identify","reset","group","track","ready","alias","debug","page","screen","once","off","on","addSourceMiddleware","addIntegrationMiddleware","setAnonymousId","addDestinationMiddleware","register"];analytics.factory=function(e){return function(){if(window[i].initialized)return window[i][e].apply(window[i],arguments);var n=Array.prototype.slice.call(arguments);if(["track","screen","alias","group","page","identify"].indexOf(e)>-1){var c=document.querySelector("link[rel='canonical']");n.push({__t:"bpc",c:c&&c.getAttribute("href")||void 0,p:location.pathname,u:location.href,s:location.search,t:document.title,r:document.referrer})}n.unshift(e);analytics.push(n);return analytics}};for(var n=0;n<analytics.methods.length;n++){var key=analytics.methods[n];analytics[key]=analytics.factory(key)}analytics.load=function(key,n){var t=document.createElement("script");t.type="text/javascript";t.async=!0;t.setAttribute("data-global-segment-analytics-key",i);t.src="https://cdn.segment.com/analytics.js/v1/" + key + "/analytics.min.js";var r=document.getElementsByTagName("script")[0];r.parentNode.insertBefore(t,r);analytics._loadOptions=n};analytics._writeKey="${segmentPublicWriteKey}";;analytics.SNIPPET_VERSION="5.2.0";
analytics.load("${segmentPublicWriteKey}");
analytics.page();
}}();
`,
},
],
};
},
};
}
module.exports = pluginSegment;