Babysitter docs-analytics
Documentation usage analytics and insights. Integrate with Google Analytics, Algolia analytics, and custom tracking to measure documentation effectiveness, identify content gaps, and optimize user journeys.
install
source · Clone the upstream repo
git clone https://github.com/a5c-ai/babysitter
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/a5c-ai/babysitter "$T" && mkdir -p ~/.claude/skills && cp -r "$T/library/specializations/technical-documentation/skills/docs-analytics" ~/.claude/skills/a5c-ai-babysitter-docs-analytics && rm -rf "$T"
manifest:
library/specializations/technical-documentation/skills/docs-analytics/SKILL.mdsource content
Documentation Analytics Skill
Measure documentation effectiveness with analytics integration, search insights, user journey analysis, and content performance metrics.
Capabilities
- Google Analytics integration for documentation sites
- Algolia analytics for search patterns
- User journey analysis and flow tracking
- Content engagement metrics
- Search query analysis and gap identification
- Page performance metrics
- Heatmap integration (Hotjar, etc.)
- Custom event tracking
- Documentation ROI measurement
Usage
Invoke this skill when you need to:
- Set up documentation analytics
- Analyze documentation usage patterns
- Identify content gaps from search data
- Measure documentation effectiveness
- Optimize user journeys through docs
Inputs
| Parameter | Type | Required | Description |
|---|---|---|---|
| docsUrl | string | Yes | Documentation site URL |
| analyticsProvider | string | No | ga4, algolia, plausible, custom |
| trackingId | string | No | Analytics tracking ID |
| algoliaAppId | string | No | Algolia application ID |
| algoliaApiKey | string | No | Algolia API key for analytics |
| enableHeatmaps | boolean | No | Enable heatmap tracking |
| customEvents | array | No | Custom events to track |
Input Example
{ "docsUrl": "https://docs.example.com", "analyticsProvider": "ga4", "trackingId": "G-XXXXXXXXXX", "algoliaAppId": "ALGOLIA_APP_ID", "enableHeatmaps": true, "customEvents": [ "code_copy", "feedback_submitted", "version_switch" ] }
Output Structure
analytics/ ├── reports/ │ ├── monthly-summary.json │ ├── search-analysis.json │ ├── content-gaps.json │ └── user-journeys.json ├── dashboards/ │ ├── overview.html │ └── search-insights.html └── config/ ├── ga4-config.json └── algolia-config.json
Google Analytics 4 Integration
GA4 Configuration
// analytics.js window.dataLayer = window.dataLayer || []; function gtag() { dataLayer.push(arguments); } gtag('js', new Date()); gtag('config', 'G-XXXXXXXXXX', { // Custom dimensions for docs custom_map: { dimension1: 'doc_version', dimension2: 'doc_section', dimension3: 'search_query', dimension4: 'code_language', }, }); // Track documentation version gtag('set', 'user_properties', { doc_version: document.querySelector('meta[name="docs-version"]')?.content, });
Custom Events
// Track code block copy document.querySelectorAll('pre code').forEach((block) => { block.addEventListener('click', () => { gtag('event', 'code_copy', { event_category: 'engagement', event_label: block.className, // language page_location: window.location.href, }); }); }); // Track documentation feedback function trackFeedback(helpful, pageUrl) { gtag('event', 'doc_feedback', { event_category: 'feedback', event_label: helpful ? 'helpful' : 'not_helpful', page_location: pageUrl, }); } // Track version switching function trackVersionSwitch(fromVersion, toVersion) { gtag('event', 'version_switch', { event_category: 'navigation', from_version: fromVersion, to_version: toVersion, }); } // Track time on page let startTime = Date.now(); window.addEventListener('beforeunload', () => { const timeSpent = Math.round((Date.now() - startTime) / 1000); gtag('event', 'time_on_page', { event_category: 'engagement', value: timeSpent, page_location: window.location.href, }); }); // Track scroll depth let maxScroll = 0; window.addEventListener('scroll', () => { const scrollPercent = Math.round( (window.scrollY / (document.body.scrollHeight - window.innerHeight)) * 100 ); if (scrollPercent > maxScroll) { maxScroll = scrollPercent; if ([25, 50, 75, 90, 100].includes(scrollPercent)) { gtag('event', 'scroll_depth', { event_category: 'engagement', value: scrollPercent, page_location: window.location.href, }); } } }); // Track external link clicks document.querySelectorAll('a[href^="http"]').forEach((link) => { link.addEventListener('click', () => { gtag('event', 'outbound_click', { event_category: 'engagement', event_label: link.href, page_location: window.location.href, }); }); });
Algolia Analytics Integration
DocSearch Analytics
// Algolia DocSearch with analytics import docsearch from '@docsearch/js'; docsearch({ appId: 'YOUR_APP_ID', apiKey: 'YOUR_SEARCH_API_KEY', indexName: 'YOUR_INDEX_NAME', container: '#docsearch', debug: false, insights: true, // Enable Algolia analytics searchParameters: { analytics: true, clickAnalytics: true, enablePersonalization: false, }, });
Search Analytics API
// Fetch search analytics from Algolia const algoliasearch = require('algoliasearch'); const analyticsClient = algoliasearch('APP_ID', 'ADMIN_API_KEY'); async function getSearchAnalytics() { const index = analyticsClient.initIndex('docs'); // Get top searches const topSearches = await analyticsClient.customRequest({ method: 'GET', path: '/2/searches', data: { index: 'docs', startDate: '2026-01-01', endDate: '2026-01-24', limit: 100, orderBy: 'searchCount', }, }); // Get searches with no results const noResultSearches = await analyticsClient.customRequest({ method: 'GET', path: '/2/searches/noResults', data: { index: 'docs', startDate: '2026-01-01', endDate: '2026-01-24', limit: 100, }, }); // Get click-through rate const clickAnalytics = await analyticsClient.customRequest({ method: 'GET', path: '/2/clicks/clickThroughRate', data: { index: 'docs', startDate: '2026-01-01', endDate: '2026-01-24', }, }); return { topSearches: topSearches.searches, noResultSearches: noResultSearches.searches, clickThroughRate: clickAnalytics, }; }
Search Gap Analysis
// Analyze search queries that return no results async function analyzeContentGaps(noResultSearches) { const gaps = []; for (const search of noResultSearches) { // Categorize by topic const category = categorizeQuery(search.search); gaps.push({ query: search.search, count: search.count, category, suggestedContent: generateContentSuggestion(search.search), priority: calculatePriority(search.count), }); } return gaps.sort((a, b) => b.count - a.count); } function categorizeQuery(query) { const categories = { api: /api|endpoint|rest|graphql|webhook/i, authentication: /auth|login|oauth|token|api.?key/i, integration: /integrate|connect|setup|install/i, error: /error|fail|issue|problem|not.?work/i, pricing: /price|cost|plan|billing/i, }; for (const [category, pattern] of Object.entries(categories)) { if (pattern.test(query)) return category; } return 'general'; }
User Journey Analysis
Journey Tracking
// Track user journey through documentation const journey = { sessionId: generateSessionId(), startTime: Date.now(), pages: [], searches: [], events: [], }; // Track page views function trackPageView(pageUrl, pageTitle) { journey.pages.push({ url: pageUrl, title: pageTitle, timestamp: Date.now(), timeOnPrevPage: calculateTimeOnPrevPage(), }); } // Track searches function trackSearch(query, results) { journey.searches.push({ query, resultsCount: results.length, timestamp: Date.now(), clickedResult: null, }); } // Track search result click function trackSearchClick(query, resultUrl, position) { const search = journey.searches.find((s) => s.query === query); if (search) { search.clickedResult = { url: resultUrl, position }; } } // Analyze journey patterns function analyzeJourney(journey) { return { totalPages: journey.pages.length, totalTime: Date.now() - journey.startTime, searchesBeforeSuccess: countSearchesBeforeSuccess(journey), commonPaths: identifyCommonPaths(journey.pages), dropOffPoints: identifyDropOffPoints(journey.pages), }; }
Common Journey Patterns
// Identify common documentation paths async function getCommonPaths(journeys) { const pathCounts = {}; journeys.forEach((journey) => { const path = journey.pages .map((p) => p.url) .slice(0, 5) .join(' -> '); pathCounts[path] = (pathCounts[path] || 0) + 1; }); return Object.entries(pathCounts) .sort((a, b) => b[1] - a[1]) .slice(0, 20) .map(([path, count]) => ({ path, count, percentage: ((count / journeys.length) * 100).toFixed(1), })); }
Content Performance Metrics
Engagement Metrics
// Calculate content engagement score function calculateEngagementScore(pageMetrics) { const weights = { avgTimeOnPage: 0.3, scrollDepth: 0.2, codeBlockInteractions: 0.2, feedbackScore: 0.15, exitRate: -0.15, // Negative weight }; return Object.entries(weights).reduce((score, [metric, weight]) => { return score + normalizeMetric(pageMetrics[metric]) * weight; }, 0); } // Page performance report function generatePageReport(pageUrl) { return { url: pageUrl, metrics: { pageviews: getPageviews(pageUrl), uniqueVisitors: getUniqueVisitors(pageUrl), avgTimeOnPage: getAvgTimeOnPage(pageUrl), bounceRate: getBounceRate(pageUrl), exitRate: getExitRate(pageUrl), scrollDepth: { '25%': getScrollDepthPercent(pageUrl, 25), '50%': getScrollDepthPercent(pageUrl, 50), '75%': getScrollDepthPercent(pageUrl, 75), '100%': getScrollDepthPercent(pageUrl, 100), }, feedback: { helpful: getHelpfulCount(pageUrl), notHelpful: getNotHelpfulCount(pageUrl), score: getFeedbackScore(pageUrl), }, codeInteractions: getCodeInteractions(pageUrl), }, engagementScore: calculateEngagementScore(pageMetrics), recommendations: generateRecommendations(pageMetrics), }; }
Content Gap Report
{ "period": "2026-01", "summary": { "totalSearches": 45230, "uniqueSearches": 8432, "noResultSearches": 1234, "avgClickThroughRate": 0.68 }, "contentGaps": [ { "query": "webhook authentication", "searchCount": 342, "category": "authentication", "suggestedContent": { "type": "guide", "title": "Webhook Authentication Guide", "outline": [ "Introduction to webhook security", "Signature verification", "Best practices" ] }, "priority": "high" }, { "query": "rate limiting best practices", "searchCount": 256, "category": "api", "suggestedContent": { "type": "guide", "title": "Rate Limiting Best Practices", "outline": [ "Understanding rate limits", "Handling 429 responses", "Exponential backoff implementation" ] }, "priority": "high" } ], "topSearches": [ { "query": "authentication", "count": 1543 }, { "query": "api keys", "count": 1232 }, { "query": "getting started", "count": 987 } ], "lowPerformingPages": [ { "url": "/docs/advanced/caching", "issues": ["high bounce rate", "low scroll depth"], "recommendations": [ "Add more code examples", "Include visual diagrams" ] } ] }
Dashboard Configuration
Docusaurus Analytics
// docusaurus.config.js module.exports = { plugins: [ [ '@docusaurus/plugin-google-gtag', { trackingID: 'G-XXXXXXXXXX', anonymizeIP: true, }, ], ], themeConfig: { algolia: { appId: 'YOUR_APP_ID', apiKey: 'YOUR_SEARCH_API_KEY', indexName: 'YOUR_INDEX_NAME', insights: true, }, }, scripts: [ { src: '/js/custom-analytics.js', async: true, }, ], };
MkDocs Analytics
# mkdocs.yml plugins: - search: analytics: provider: algolia property: YOUR_INDEX_NAME extra: analytics: provider: google property: G-XXXXXXXXXX feedback: title: Was this page helpful? ratings: - icon: material/emoticon-happy-outline name: This page was helpful data: 1 note: Thanks for your feedback! - icon: material/emoticon-sad-outline name: This page could be improved data: 0 note: Thanks! Help us improve by using the feedback form.
Workflow
- Configure analytics - Set up GA4 and/or Algolia
- Implement tracking - Add custom event tracking
- Collect data - Gather usage metrics
- Analyze patterns - Identify trends and gaps
- Generate reports - Create actionable insights
- Optimize content - Improve based on data
Dependencies
{ "dependencies": { "algoliasearch": "^4.0.0", "@docsearch/js": "^3.0.0" }, "devDependencies": { "@google-analytics/data": "^4.0.0" } }
Best Practices Applied
- Track meaningful events, not just pageviews
- Analyze search queries for content gaps
- Measure engagement beyond time on page
- Create actionable insights from data
- Respect user privacy (GDPR compliance)
- Focus on documentation ROI
References
- Google Analytics 4: https://developers.google.com/analytics/devguides/collection/ga4
- Algolia Analytics: https://www.algolia.com/doc/guides/search-analytics/overview/
- DocSearch: https://docsearch.algolia.com/
- Privacy-friendly: https://plausible.io/
Target Processes
- docs-audit.js
- content-strategy.js
- knowledge-base-setup.js
- docs-testing.js