feat: P1通用功能:4个Hook创建完成(待集成)现在您可以追踪:
1. 完整的用户旅程
- 从进入网站 → 浏览内容 → 使用功能 → 遇到付费墙 → 付费转化
2. 核心业务指标
- DAU/MAU(活跃用户)
- 功能使用率(哪些功能最受欢迎)
- 搜索热度(用户需求洞察)
- Revenue转化漏斗(付费转化分析)
- 用户参与度(Profile更新、设置变更)
3. 产品优化方向
- 哪些功能需要优化?
- 用户在哪个环节流失?
- 哪些内容最受欢迎?
- 如何提高付费转化率?
This commit is contained in:
334
src/hooks/useProfileEvents.js
Normal file
334
src/hooks/useProfileEvents.js
Normal 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;
|
||||
Reference in New Issue
Block a user