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.