feat: P1通用功能:4个Hook创建完成(待集成)现在您可以追踪:

1. 完整的用户旅程
    - 从进入网站 → 浏览内容 → 使用功能 → 遇到付费墙 → 付费转化
  2. 核心业务指标
    - DAU/MAU(活跃用户)
    - 功能使用率(哪些功能最受欢迎)
    - 搜索热度(用户需求洞察)
    - Revenue转化漏斗(付费转化分析)
    - 用户参与度(Profile更新、设置变更)
  3. 产品优化方向
    - 哪些功能需要优化?
    - 用户在哪个环节流失?
    - 哪些内容最受欢迎?
    - 如何提高付费转化率?
This commit is contained in:
zdl
2025-10-29 12:01:26 +08:00
parent 78e4b8f696
commit e3a953559f
4 changed files with 1265 additions and 0 deletions

View File

@@ -0,0 +1,334 @@
// src/hooks/useProfileEvents.js
// 个人资料和设置事件追踪 Hook
import { useCallback } from 'react';
import { usePostHogTrack } from './usePostHogRedux';
import { RETENTION_EVENTS } from '../lib/constants';
import { logger } from '../utils/logger';
/**
* 个人资料和设置事件追踪 Hook
* @param {Object} options - 配置选项
* @param {string} options.pageType - 页面类型 ('profile' | 'settings' | 'security')
* @returns {Object} 事件追踪处理函数集合
*/
export const useProfileEvents = ({ pageType = 'profile' } = {}) => {
const { track } = usePostHogTrack();
/**
* 追踪个人资料字段编辑开始
* @param {string} fieldName - 字段名称 ('nickname' | 'email' | 'phone' | 'avatar' | 'bio')
*/
const trackProfileFieldEditStarted = useCallback((fieldName) => {
if (!fieldName) {
logger.warn('useProfileEvents', 'trackProfileFieldEditStarted: fieldName is required');
return;
}
track('Profile Field Edit Started', {
field_name: fieldName,
page_type: pageType,
timestamp: new Date().toISOString(),
});
logger.debug('useProfileEvents', '✏️ Profile Field Edit Started', {
fieldName,
pageType,
});
}, [track, pageType]);
/**
* 追踪个人资料更新成功
* @param {Array<string>} updatedFields - 更新的字段列表
* @param {Object} changes - 变更详情
*/
const trackProfileUpdated = useCallback((updatedFields = [], changes = {}) => {
if (!updatedFields || updatedFields.length === 0) {
logger.warn('useProfileEvents', 'trackProfileUpdated: updatedFields array is required');
return;
}
track(RETENTION_EVENTS.PROFILE_UPDATED, {
updated_fields: updatedFields,
field_count: updatedFields.length,
changes: changes,
page_type: pageType,
timestamp: new Date().toISOString(),
});
logger.debug('useProfileEvents', '✅ Profile Updated', {
updatedFields,
fieldCount: updatedFields.length,
pageType,
});
}, [track, pageType]);
/**
* 追踪个人资料更新失败
* @param {Array<string>} attemptedFields - 尝试更新的字段
* @param {string} errorMessage - 错误信息
*/
const trackProfileUpdateFailed = useCallback((attemptedFields = [], errorMessage = '') => {
track('Profile Update Failed', {
attempted_fields: attemptedFields,
error_message: errorMessage,
page_type: pageType,
timestamp: new Date().toISOString(),
});
logger.debug('useProfileEvents', '❌ Profile Update Failed', {
attemptedFields,
errorMessage,
pageType,
});
}, [track, pageType]);
/**
* 追踪头像上传
* @param {string} uploadMethod - 上传方式 ('file_upload' | 'url' | 'camera' | 'default_avatar')
* @param {number} fileSize - 文件大小bytes
*/
const trackAvatarUploaded = useCallback((uploadMethod = 'file_upload', fileSize = 0) => {
track('Avatar Uploaded', {
upload_method: uploadMethod,
file_size: fileSize,
file_size_mb: (fileSize / (1024 * 1024)).toFixed(2),
page_type: pageType,
timestamp: new Date().toISOString(),
});
logger.debug('useProfileEvents', '🖼️ Avatar Uploaded', {
uploadMethod,
fileSize,
pageType,
});
}, [track, pageType]);
/**
* 追踪密码更改
* @param {boolean} success - 是否成功
* @param {string} errorReason - 失败原因
*/
const trackPasswordChanged = useCallback((success = true, errorReason = '') => {
track('Password Changed', {
success,
error_reason: errorReason || null,
page_type: pageType,
timestamp: new Date().toISOString(),
});
logger.debug('useProfileEvents', success ? '🔒 Password Changed Successfully' : '❌ Password Change Failed', {
success,
errorReason,
pageType,
});
}, [track, pageType]);
/**
* 追踪邮箱验证发起
* @param {string} email - 邮箱地址
*/
const trackEmailVerificationSent = useCallback((email = '') => {
track('Email Verification Sent', {
email_provided: Boolean(email),
page_type: pageType,
timestamp: new Date().toISOString(),
});
logger.debug('useProfileEvents', '📧 Email Verification Sent', {
emailProvided: Boolean(email),
pageType,
});
}, [track, pageType]);
/**
* 追踪手机号验证发起
* @param {string} phone - 手机号
*/
const trackPhoneVerificationSent = useCallback((phone = '') => {
track('Phone Verification Sent', {
phone_provided: Boolean(phone),
page_type: pageType,
timestamp: new Date().toISOString(),
});
logger.debug('useProfileEvents', '📱 Phone Verification Sent', {
phoneProvided: Boolean(phone),
pageType,
});
}, [track, pageType]);
/**
* 追踪账号绑定(微信、邮箱、手机等)
* @param {string} accountType - 账号类型 ('wechat' | 'email' | 'phone')
* @param {boolean} success - 是否成功
*/
const trackAccountBound = useCallback((accountType, success = true) => {
if (!accountType) {
logger.warn('useProfileEvents', 'trackAccountBound: accountType is required');
return;
}
track('Account Bound', {
account_type: accountType,
success,
page_type: pageType,
timestamp: new Date().toISOString(),
});
logger.debug('useProfileEvents', success ? '🔗 Account Bound' : '❌ Account Bind Failed', {
accountType,
success,
pageType,
});
}, [track, pageType]);
/**
* 追踪账号解绑
* @param {string} accountType - 账号类型
* @param {boolean} success - 是否成功
*/
const trackAccountUnbound = useCallback((accountType, success = true) => {
if (!accountType) {
logger.warn('useProfileEvents', 'trackAccountUnbound: accountType is required');
return;
}
track('Account Unbound', {
account_type: accountType,
success,
page_type: pageType,
timestamp: new Date().toISOString(),
});
logger.debug('useProfileEvents', success ? '🔓 Account Unbound' : '❌ Account Unbind Failed', {
accountType,
success,
pageType,
});
}, [track, pageType]);
/**
* 追踪设置项更改
* @param {string} settingName - 设置名称
* @param {any} oldValue - 旧值
* @param {any} newValue - 新值
* @param {string} category - 设置分类 ('notification' | 'privacy' | 'display' | 'advanced')
*/
const trackSettingChanged = useCallback((settingName, oldValue, newValue, category = 'general') => {
if (!settingName) {
logger.warn('useProfileEvents', 'trackSettingChanged: settingName is required');
return;
}
track(RETENTION_EVENTS.SETTINGS_CHANGED, {
setting_name: settingName,
old_value: String(oldValue),
new_value: String(newValue),
category,
page_type: pageType,
timestamp: new Date().toISOString(),
});
logger.debug('useProfileEvents', '⚙️ Setting Changed', {
settingName,
oldValue,
newValue,
category,
pageType,
});
}, [track, pageType]);
/**
* 追踪通知偏好更改
* @param {Object} preferences - 通知偏好设置
* @param {boolean} preferences.email - 邮件通知
* @param {boolean} preferences.push - 推送通知
* @param {boolean} preferences.sms - 短信通知
*/
const trackNotificationPreferencesChanged = useCallback((preferences = {}) => {
track('Notification Preferences Changed', {
email_enabled: preferences.email || false,
push_enabled: preferences.push || false,
sms_enabled: preferences.sms || false,
total_enabled: Object.values(preferences).filter(Boolean).length,
page_type: pageType,
timestamp: new Date().toISOString(),
});
logger.debug('useProfileEvents', '🔔 Notification Preferences Changed', {
preferences,
pageType,
});
}, [track, pageType]);
/**
* 追踪隐私设置更改
* @param {string} privacySetting - 隐私设置名称
* @param {boolean} isPublic - 是否公开
*/
const trackPrivacySettingChanged = useCallback((privacySetting, isPublic = false) => {
if (!privacySetting) {
logger.warn('useProfileEvents', 'trackPrivacySettingChanged: privacySetting is required');
return;
}
track('Privacy Setting Changed', {
privacy_setting: privacySetting,
is_public: isPublic,
page_type: pageType,
timestamp: new Date().toISOString(),
});
logger.debug('useProfileEvents', '🔐 Privacy Setting Changed', {
privacySetting,
isPublic,
pageType,
});
}, [track, pageType]);
/**
* 追踪账号删除请求
* @param {string} reason - 删除原因
*/
const trackAccountDeletionRequested = useCallback((reason = '') => {
track('Account Deletion Requested', {
reason,
has_reason: Boolean(reason),
page_type: pageType,
timestamp: new Date().toISOString(),
});
logger.debug('useProfileEvents', '🗑️ Account Deletion Requested', {
reason,
pageType,
});
}, [track, pageType]);
return {
// 个人资料编辑
trackProfileFieldEditStarted,
trackProfileUpdated,
trackProfileUpdateFailed,
trackAvatarUploaded,
// 安全和验证
trackPasswordChanged,
trackEmailVerificationSent,
trackPhoneVerificationSent,
// 账号绑定
trackAccountBound,
trackAccountUnbound,
// 设置更改
trackSettingChanged,
trackNotificationPreferencesChanged,
trackPrivacySettingChanged,
// 账号管理
trackAccountDeletionRequested,
};
};
export default useProfileEvents;