feat: PostHog 集成\

1.  安装依赖: posthog-js@^1.280.1
  2.  创建核心文件:
    - src/lib/posthog.js - PostHog SDK 封装(271 行)
    - src/lib/constants.js - 事件常量定义(AARRR 框架)
    - src/hooks/usePostHog.js - PostHog React Hook
    - src/hooks/usePageTracking.js - 页面追踪 Hook
    - src/components/PostHogProvider.js - Provider 组件
  3.  集成到应用:
    - 修改 src/App.js,在最外层添加 <PostHogProvider>
    - 自动追踪所有页面浏览
  4.  配置环境变量:
    - 在 .env 添加 PostHog 配置项
    - REACT_APP_POSTHOG_KEY 留空,需要用户填写
  5.  创建文档: POSTHOG_INTEGRATION.md 包含完整的使用说明
This commit is contained in:
zdl
2025-10-28 20:09:21 +08:00
parent 542b20368e
commit 6506cb222b
7 changed files with 892 additions and 27 deletions

351
src/lib/constants.js Normal file
View File

@@ -0,0 +1,351 @@
// src/lib/constants.js
// PostHog Event Names and Constants
// Organized by AARRR Framework (Acquisition, Activation, Retention, Referral, Revenue)
// ============================================================================
// ACQUISITION (获客) - Landing page, marketing website events
// ============================================================================
export const ACQUISITION_EVENTS = {
// Landing page
LANDING_PAGE_VIEWED: 'Landing Page Viewed',
CTA_BUTTON_CLICKED: 'CTA Button Clicked',
FEATURE_CARD_VIEWED: 'Feature Card Viewed',
FEATURE_VIDEO_PLAYED: 'Feature Video Played',
// Pricing page
PRICING_PAGE_VIEWED: 'Pricing Page Viewed',
PRICING_PLAN_VIEWED: 'Pricing Plan Viewed',
PRICING_PLAN_SELECTED: 'Pricing Plan Selected',
// How to use page
HOW_TO_USE_PAGE_VIEWED: 'How To Use Page Viewed',
TUTORIAL_STEP_VIEWED: 'Tutorial Step Viewed',
// Roadmap page
ROADMAP_PAGE_VIEWED: 'Roadmap Page Viewed',
ROADMAP_ITEM_CLICKED: 'Roadmap Item Clicked',
};
// ============================================================================
// ACTIVATION (激活) - Sign up, login, onboarding
// ============================================================================
export const ACTIVATION_EVENTS = {
// Auth pages
LOGIN_PAGE_VIEWED: 'Login Page Viewed',
SIGNUP_PAGE_VIEWED: 'Signup Page Viewed',
// Login/Signup actions
LOGIN_METHOD_SELECTED: 'Login Method Selected', // wechat, email, phone
WECHAT_QR_DISPLAYED: 'WeChat QR Code Displayed',
WECHAT_QR_SCANNED: 'WeChat QR Code Scanned',
USER_LOGGED_IN: 'User Logged In',
USER_SIGNED_UP: 'User Signed Up',
VERIFICATION_CODE_SENT: 'Verification Code Sent',
VERIFICATION_CODE_SUBMITTED: 'Verification Code Submitted',
LOGIN_FAILED: 'Login Failed',
SIGNUP_FAILED: 'Signup Failed',
// Onboarding
ONBOARDING_STARTED: 'Onboarding Started',
ONBOARDING_STEP_COMPLETED: 'Onboarding Step Completed',
ONBOARDING_COMPLETED: 'Onboarding Completed',
ONBOARDING_SKIPPED: 'Onboarding Skipped',
// User agreement
USER_AGREEMENT_VIEWED: 'User Agreement Viewed',
USER_AGREEMENT_ACCEPTED: 'User Agreement Accepted',
PRIVACY_POLICY_VIEWED: 'Privacy Policy Viewed',
PRIVACY_POLICY_ACCEPTED: 'Privacy Policy Accepted',
};
// ============================================================================
// RETENTION (留存) - Core product usage, feature engagement
// ============================================================================
export const RETENTION_EVENTS = {
// Dashboard
DASHBOARD_VIEWED: 'Dashboard Viewed',
DASHBOARD_CENTER_VIEWED: 'Dashboard Center Viewed',
FUNCTION_CARD_CLICKED: 'Function Card Clicked', // Core功能卡片点击
// Navigation
TOP_NAV_CLICKED: 'Top Navigation Clicked',
SIDEBAR_MENU_CLICKED: 'Sidebar Menu Clicked',
MENU_ITEM_CLICKED: 'Menu Item Clicked',
BREADCRUMB_CLICKED: 'Breadcrumb Clicked',
// Search
SEARCH_INITIATED: 'Search Initiated',
SEARCH_QUERY_SUBMITTED: 'Search Query Submitted',
SEARCH_RESULT_CLICKED: 'Search Result Clicked',
SEARCH_NO_RESULTS: 'Search No Results',
SEARCH_FILTER_APPLIED: 'Search Filter Applied',
// News/Community (新闻催化分析)
COMMUNITY_PAGE_VIEWED: 'Community Page Viewed',
NEWS_LIST_VIEWED: 'News List Viewed',
NEWS_ARTICLE_CLICKED: 'News Article Clicked',
NEWS_DETAIL_OPENED: 'News Detail Opened',
NEWS_TAB_CLICKED: 'News Tab Clicked', // 相关标的, 相关概念, etc.
NEWS_FILTER_APPLIED: 'News Filter Applied',
NEWS_SORTED: 'News Sorted',
// Concept Center (概念中心)
CONCEPT_PAGE_VIEWED: 'Concept Page Viewed',
CONCEPT_LIST_VIEWED: 'Concept List Viewed',
CONCEPT_CLICKED: 'Concept Clicked',
CONCEPT_DETAIL_VIEWED: 'Concept Detail Viewed',
CONCEPT_STOCK_CLICKED: 'Concept Stock Clicked',
// Stock Center (个股中心)
STOCK_OVERVIEW_VIEWED: 'Stock Overview Page Viewed',
STOCK_LIST_VIEWED: 'Stock List Viewed',
STOCK_SEARCHED: 'Stock Searched',
STOCK_CLICKED: 'Stock Clicked',
STOCK_DETAIL_VIEWED: 'Stock Detail Viewed',
STOCK_TAB_CLICKED: 'Stock Tab Clicked', // 公司概览, 股票行情, 财务全景, 盈利预测
// Company Details
COMPANY_OVERVIEW_VIEWED: 'Company Overview Viewed',
COMPANY_FINANCIALS_VIEWED: 'Company Financials Viewed',
COMPANY_FORECAST_VIEWED: 'Company Forecast Viewed',
COMPANY_MARKET_DATA_VIEWED: 'Company Market Data Viewed',
// Limit Analysis (涨停分析)
LIMIT_ANALYSE_PAGE_VIEWED: 'Limit Analyse Page Viewed',
LIMIT_BOARD_CLICKED: 'Limit Board Clicked',
LIMIT_SECTOR_EXPANDED: 'Limit Sector Expanded',
LIMIT_SECTOR_ANALYSIS_VIEWED: 'Limit Sector Analysis Viewed',
LIMIT_STOCK_CLICKED: 'Limit Stock Clicked',
// Trading Simulation (模拟盘交易)
TRADING_SIMULATION_ENTERED: 'Trading Simulation Entered',
SIMULATION_ORDER_PLACED: 'Simulation Order Placed',
SIMULATION_HOLDINGS_VIEWED: 'Simulation Holdings Viewed',
SIMULATION_HISTORY_VIEWED: 'Simulation History Viewed',
SIMULATION_STOCK_SEARCHED: 'Simulation Stock Searched',
// Event Details
EVENT_DETAIL_VIEWED: 'Event Detail Viewed',
EVENT_ANALYSIS_VIEWED: 'Event Analysis Viewed',
EVENT_TIMELINE_CLICKED: 'Event Timeline Clicked',
// Profile & Settings
PROFILE_PAGE_VIEWED: 'Profile Page Viewed',
PROFILE_UPDATED: 'Profile Updated',
SETTINGS_PAGE_VIEWED: 'Settings Page Viewed',
SETTINGS_CHANGED: 'Settings Changed',
// Subscription Management
SUBSCRIPTION_PAGE_VIEWED: 'Subscription Page Viewed',
UPGRADE_PLAN_CLICKED: 'Upgrade Plan Clicked',
};
// ============================================================================
// REFERRAL (推荐) - Sharing, inviting
// ============================================================================
export const REFERRAL_EVENTS = {
// Sharing
SHARE_BUTTON_CLICKED: 'Share Button Clicked',
CONTENT_SHARED: 'Content Shared',
SHARE_LINK_GENERATED: 'Share Link Generated',
SHARE_MODAL_OPENED: 'Share Modal Opened',
SHARE_MODAL_CLOSED: 'Share Modal Closed',
// Referral
REFERRAL_PAGE_VIEWED: 'Referral Page Viewed',
REFERRAL_LINK_COPIED: 'Referral Link Copied',
REFERRAL_INVITE_SENT: 'Referral Invite Sent',
};
// ============================================================================
// REVENUE (收入) - Payment, subscription, monetization
// ============================================================================
export const REVENUE_EVENTS = {
// Paywall
PAYWALL_SHOWN: 'Paywall Shown',
PAYWALL_DISMISSED: 'Paywall Dismissed',
PAYWALL_UPGRADE_CLICKED: 'Paywall Upgrade Clicked',
// Payment
PAYMENT_PAGE_VIEWED: 'Payment Page Viewed',
PAYMENT_METHOD_SELECTED: 'Payment Method Selected',
PAYMENT_INITIATED: 'Payment Initiated',
PAYMENT_SUCCESSFUL: 'Payment Successful',
PAYMENT_FAILED: 'Payment Failed',
// Subscription
SUBSCRIPTION_CREATED: 'Subscription Created',
SUBSCRIPTION_RENEWED: 'Subscription Renewed',
SUBSCRIPTION_UPGRADED: 'Subscription Upgraded',
SUBSCRIPTION_DOWNGRADED: 'Subscription Downgraded',
SUBSCRIPTION_CANCELLED: 'Subscription Cancelled',
SUBSCRIPTION_EXPIRED: 'Subscription Expired',
// Refund
REFUND_REQUESTED: 'Refund Requested',
REFUND_PROCESSED: 'Refund Processed',
};
// ============================================================================
// SPECIAL EVENTS (特殊事件) - Errors, performance, chatbot
// ============================================================================
export const SPECIAL_EVENTS = {
// Errors
ERROR_OCCURRED: 'Error Occurred',
API_ERROR: 'API Error',
NOT_FOUND_404: '404 Not Found',
// Performance
PAGE_LOAD_TIME: 'Page Load Time',
API_RESPONSE_TIME: 'API Response Time',
// Chatbot (Dify)
CHATBOT_OPENED: 'Chatbot Opened',
CHATBOT_CLOSED: 'Chatbot Closed',
CHATBOT_MESSAGE_SENT: 'Chatbot Message Sent',
CHATBOT_MESSAGE_RECEIVED: 'Chatbot Message Received',
CHATBOT_FEEDBACK_PROVIDED: 'Chatbot Feedback Provided',
// Scroll depth
SCROLL_DEPTH_25: 'Scroll Depth 25%',
SCROLL_DEPTH_50: 'Scroll Depth 50%',
SCROLL_DEPTH_75: 'Scroll Depth 75%',
SCROLL_DEPTH_100: 'Scroll Depth 100%',
// Session
SESSION_STARTED: 'Session Started',
SESSION_ENDED: 'Session Ended',
USER_IDLE: 'User Idle',
USER_RETURNED: 'User Returned',
// Logout
USER_LOGGED_OUT: 'User Logged Out',
};
// ============================================================================
// USER PROPERTIES (用户属性)
// ============================================================================
export const USER_PROPERTIES = {
// Identity
EMAIL: 'email',
USERNAME: 'username',
USER_ID: 'user_id',
PHONE: 'phone',
// Subscription
SUBSCRIPTION_TIER: 'subscription_tier', // 'free', 'pro', 'enterprise'
SUBSCRIPTION_STATUS: 'subscription_status', // 'active', 'expired', 'cancelled'
SUBSCRIPTION_START_DATE: 'subscription_start_date',
SUBSCRIPTION_END_DATE: 'subscription_end_date',
// Engagement
REGISTRATION_DATE: 'registration_date',
LAST_LOGIN: 'last_login',
LOGIN_COUNT: 'login_count',
DAYS_SINCE_REGISTRATION: 'days_since_registration',
LIFETIME_VALUE: 'lifetime_value',
// Preferences
PREFERRED_LANGUAGE: 'preferred_language',
THEME_PREFERENCE: 'theme_preference', // 'light', 'dark'
NOTIFICATION_ENABLED: 'notification_enabled',
// Attribution
UTM_SOURCE: 'utm_source',
UTM_MEDIUM: 'utm_medium',
UTM_CAMPAIGN: 'utm_campaign',
REFERRER: 'referrer',
// Behavioral
FAVORITE_FEATURES: 'favorite_features',
MOST_VISITED_PAGES: 'most_visited_pages',
TOTAL_SESSIONS: 'total_sessions',
AVERAGE_SESSION_DURATION: 'average_session_duration',
};
// ============================================================================
// SUBSCRIPTION TIERS (订阅等级)
// ============================================================================
export const SUBSCRIPTION_TIERS = {
FREE: 'free',
PRO: 'pro',
ENTERPRISE: 'enterprise',
};
// ============================================================================
// PAGE TYPES (页面类型)
// ============================================================================
export const PAGE_TYPES = {
LANDING: 'landing',
DASHBOARD: 'dashboard',
FEATURE: 'feature',
DETAIL: 'detail',
AUTH: 'auth',
SETTINGS: 'settings',
PAYMENT: 'payment',
ERROR: 'error',
};
// ============================================================================
// CONTENT TYPES (内容类型)
// ============================================================================
export const CONTENT_TYPES = {
NEWS: 'news',
STOCK: 'stock',
CONCEPT: 'concept',
ANALYSIS: 'analysis',
EVENT: 'event',
COMPANY: 'company',
};
// ============================================================================
// SHARE CHANNELS (分享渠道)
// ============================================================================
export const SHARE_CHANNELS = {
WECHAT: 'wechat',
LINK: 'link',
QRCODE: 'qrcode',
EMAIL: 'email',
COPY: 'copy',
};
// ============================================================================
// LOGIN METHODS (登录方式)
// ============================================================================
export const LOGIN_METHODS = {
WECHAT: 'wechat',
EMAIL: 'email',
PHONE: 'phone',
USERNAME: 'username',
};
// ============================================================================
// PAYMENT METHODS (支付方式)
// ============================================================================
export const PAYMENT_METHODS = {
WECHAT_PAY: 'wechat_pay',
ALIPAY: 'alipay',
CREDIT_CARD: 'credit_card',
};
// ============================================================================
// Helper function to get all events
// ============================================================================
export const getAllEvents = () => {
return {
...ACQUISITION_EVENTS,
...ACTIVATION_EVENTS,
...RETENTION_EVENTS,
...REFERRAL_EVENTS,
...REVENUE_EVENTS,
...SPECIAL_EVENTS,
};
};
// ============================================================================
// Helper function to validate event name
// ============================================================================
export const isValidEvent = (eventName) => {
const allEvents = getAllEvents();
return Object.values(allEvents).includes(eventName);
};