⚡

文档分析能力Skill docs-analytics

集成Google Analytics和Algolia分析,通过用户旅程分析和内容性能指标来衡量和优化文档的有效性。

DevOps 0 次安装 8 次浏览 更新于 2/26/2026

文档分析能力

通过集成分析、搜索洞察、用户旅程分析和内容性能指标来衡量文档的有效性。

功能

  • 集成Google Analytics进行文档站点分析
  • 集成Algolia分析搜索模式
  • 用户旅程分析和流程跟踪
  • 内容参与度指标
  • 搜索查询分析和差距识别
  • 页面性能指标
  • 热图集成(Hotjar等)
  • 自定义事件跟踪
  • 文档ROI测量

使用

当您需要:

  • 设置文档分析
  • 分析文档使用模式
  • 从搜索数据中识别内容差距
  • 衡量文档有效性
  • 通过文档优化用户旅程

输入

参数 类型 必需 描述
docsUrl string 是 文档站点URL
analyticsProvider string 否 ga4, algolia, plausible, custom
trackingId string 否 分析跟踪ID
algoliaAppId string 否 Algolia应用程序ID
algoliaApiKey string 否 Algolia API密钥用于分析
enableHeatmaps boolean 否 启用热图跟踪
customEvents array 否 要跟踪的自定义事件

输入示例

{
  "docsUrl": "https://docs.example.com",
  "analyticsProvider": "ga4",
  "trackingId": "G-XXXXXXXXXX",
  "algoliaAppId": "ALGOLIA_APP_ID",
  "enableHeatmaps": true,
  "customEvents": [
    "code_copy",
    "feedback_submitted",
    "version_switch"
  ]
}

输出结构

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集成

GA4配置

// analytics.js
window.dataLayer = window.dataLayer || [];
function gtag() {
  dataLayer.push(arguments);
}gtag('js', new Date());
gtag('config', 'G-XXXXXXXXXX', {
  // 自定义维度用于文档
  custom_map: {
    dimension1: 'doc_version',
    dimension2: 'doc_section',
    dimension3: 'search_query',
    dimension4: 'code_language',
  },
});

// 跟踪文档版本
gtag('set', 'user_properties', {
  doc_version: document.querySelector('meta[name="docs-version"]')?.content,
});

自定义事件

// 跟踪代码块复制
document.querySelectorAll('pre code').forEach((block) => {
  block.addEventListener('click', () => {
    gtag('event', 'code_copy', {
      event_category: 'engagement',
      event_label: block.className, // 语言
      page_location: window.location.href,
    });
  });
});

// 跟踪文档反馈
function trackFeedback(helpful, pageUrl) {
  gtag('event', 'doc_feedback', {
    event_category: 'feedback',
    event_label: helpful ? 'helpful' : 'not_helpful',
    page_location: pageUrl,
  });
}

// 跟踪版本切换
function trackVersionSwitch(fromVersion, toVersion) {
  gtag('event', 'version_switch', {
    event_category: 'navigation',
    from_version: fromVersion,
    to_version: toVersion,
  });
}

// 跟踪页面停留时间
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,
  });
});

// 跟踪滚动深度
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,
      });
    }
  }
});

// 跟踪外部链接点击
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分析集成

DocSearch分析

// Algolia DocSearch带分析
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, // 启用Algolia分析
  searchParameters: {
    analytics: true,
    clickAnalytics: true,
    enablePersonalization: false,
  },
});

搜索分析API

// 从Algolia获取搜索分析
const algoliasearch = require('algoliasearch');
const analyticsClient = algoliasearch('APP_ID', 'ADMIN_API_KEY');

async function getSearchAnalytics() {
  const index = analyticsClient.initIndex('docs');

  // 获取热门搜索
  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',
    },
  });

  // 获取无结果搜索
  const noResultSearches = await analyticsClient.customRequest({
    method: 'GET',
    path: '/2/searches/noResults',
    data: {
      index: 'docs',
      startDate: '2026-01-01',
      endDate: '2026-01-24',
      limit: 100,
    },
  });

  // 获取点击率
  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,
  };
}

搜索差距分析

// 分析返回无结果的搜索查询
async function analyzeContentGaps(noResultSearches) {
  const gaps = [];

  for (const search of noResultSearches) {
    // 按主题分类
    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';
}

用户旅程分析

旅程跟踪

// 跟踪用户通过文档的旅程
const journey = {
  sessionId: generateSessionId(),
  startTime: Date.now(),
  pages: [],
  searches: [],
  events: [],
};

// 跟踪页面浏览
function trackPageView(pageUrl, pageTitle) {
  journey.pages.push({
    url: pageUrl,
    title: pageTitle,
    timestamp: Date.now(),
    timeOnPrevPage: calculateTimeOnPrevPage(),
  });
}

// 跟踪搜索
function trackSearch(query, results) {
  journey.searches.push({
    query,
    resultsCount: results.length,
    timestamp: Date.now(),
    clickedResult: null,
  });
}

// 跟踪搜索结果点击
function trackSearchClick(query, resultUrl, position) {
  const search = journey.searches.find((s) => s.query === query);
  if (search) {
    search.clickedResult = { url: resultUrl, position };
  }
}

// 分析旅程模式
function analyzeJourney(journey) {
  return {
    totalPages: journey.pages.length,
    totalTime: Date.now() - journey.startTime,
    searchesBeforeSuccess: countSearchesBeforeSuccess(journey),
    commonPaths: identifyCommonPaths(journey.pages),
    dropOffPoints: identifyDropOffPoints(journey.pages),
  };
}

常见旅程模式

// 识别常见文档路径
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),
    }));
}

内容性能指标

参与度指标

// 计算内容参与度得分
function calculateEngagementScore(pageMetrics) {
  const weights = {
    avgTimeOnPage: 0.3,
    scrollDepth: 0.2,
    codeBlockInteractions: 0.2,
    feedbackScore: 0.15,
    exitRate: -0.15, // 负权重
  };

  return Object.entries(weights).reduce((score, [metric, weight]) => {
    return score + normalizeMetric(pageMetrics[metric]) * weight;
  }, 0);
}

// 页面性能报告
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),
  };
}

内容差距报告

{
  "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"
      ]
    }
  ]
}

仪表板配置

Docusaurus分析

// 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分析

# 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.

工作流程

  1. 配置分析 - 设置GA4和/或Algolia
  2. 实施跟踪 - 添加自定义事件跟踪
  3. 收集数据 - 收集使用度量
  4. 分析模式 - 识别趋势和差距
  5. 生成报告 - 创建可操作的洞察
  6. 优化内容 - 基于数据改进

依赖关系

{
  "dependencies": {
    "algoliasearch": "^4.0.0",
    "@docsearch/js": "^3.0.0"
  },
  "devDependencies": {
    "@google-analytics/data": "^4.0.0"
  }
}

最佳实践应用

  • 跟踪有意义的事件,不仅仅是页面浏览
  • 分析搜索查询以发现内容差距
  • 超越页面停留时间的参与度测量
  • 从数据中创建可操作的洞察
  • 尊重用户隐私(GDPR合规)
  • 专注于文档ROI

参考

目标流程

  • docs-audit.js
  • content-strategy.js
  • knowledge-base-setup.js
  • docs-testing.js