Files
fangke/server/tracker/constants.py
T
浅念 59de51c062 feat: 来源归因规则引擎(渠道/AI/搜索词/诚实状态/历史重算)
- constants 规则库 v1:AI/引擎/社交域名表、搜索词参数白名单、付费点击参数、
  应用内 UA 标记、CHANNELS 枚举;page_view 白名单开 nav_type/prerendering
- services/attribution.classify 纯函数:付费>AI>引擎>社交>referral 分层,
  UTM 证据叠加(combined/conflict/label_only),应用内 UA 叠加/兜底,
  引擎 TLD 国家 variant,搜索词白名单提取(Google 恒空不虚构)
- SourceClassification 派生表(迁移 0004):first_touch/session_entry 双 scope,
  rule_version 可追溯
- ingest 增量 best-effort:首访客/新会话时分类落库(savepoint+静默,
  失败不影响采集);validation 对 page_view referrer 完整 URL 参数清洗+截500
- recompute_attribution 命令:全量/按站幂等重算
- API:访客列表归因五字段+channel 筛选、详情 attribution 块(含最近5会话入口)、
  dashboard channels 聚合(sources 原口径保留);TS VisitorListParams 加 channel
- 测试 97 → 124(引擎20 + 集成/接口7)

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-16 17:03:15 +08:00

52 lines
2.9 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
EVENT_NAMES = {"page_view", "page_stay", "sdk_loaded"}
MAX_EVENTS_PER_BATCH = 50
MAX_PROP_KEYS = 32
MAX_STR_LEN = 500
MAX_PATH_LEN = 500
MAX_TITLE_LEN = 200
CLOCK_SKEW_LATE_SEC = 120 # 超过即标 late
CLOCK_SKEW_REJECT_SEC = 86400 # 超过即拒绝
SENSITIVE_KEY_PATTERNS = ("password", "passwd", "token", "secret", "card", "verif", "otp", "idcard")
URL_PARAM_DROP_PATTERNS = ("email", "phone", "mobile", "token", "key", "password", "verif")
SESSION_IDLE_MS = 30 * 60 * 1000
BOT_UA_KEYWORDS = ("bot", "spider", "crawl", "slurp", "bingpreview", "headless", "lighthouse")
EVENT_PROP_WHITELIST = { # spec §9.1:未知字段拒绝。免费文本/任意属性不得入库
"page_view": {"referrer", "referrer_domain", "utm", "nav_type", "prerendering"},
"page_stay": {"active_ms", "path"},
"sdk_loaded": {"sdk_version"},
}
MAX_PROP_DEPTH = 2
MAX_PROP_JSON_BYTES = 4096
# ---------------------------------------------------------------------------
# 来源归因规则库 v1(tracker/services/attribution.py 消费)。改规则必须 bump 版本号
# 并跑 recompute_attribution 重算历史——已落库分类带 rule_version 可追溯。
# ---------------------------------------------------------------------------
ATTRIBUTION_RULE_VERSION = "v1"
AI_REFERRAL_DOMAINS = { # AI 平台 → 显示名
"chatgpt.com": "ChatGPT", "perplexity.ai": "Perplexity",
"copilot.microsoft.com": "Copilot", "gemini.google.com": "Gemini",
"deepseek.com": "DeepSeek", "claude.ai": "Claude", "poe.com": "Poe", "you.com": "You",
}
SEARCH_ENGINE_DOMAINS = { # 引擎后缀/域名 → 显示名("google."/"yandex." 前缀匹配任意国家站 TLD)
"google.": "Google", "bing.com": "Bing", "baidu.com": "百度", "yandex.": "Yandex",
"duckduckgo.com": "DuckDuckGo", "yahoo.com": "Yahoo", "ecosia.org": "Ecosia",
"search.naver.com": "Naver", "search.brave.com": "Brave",
}
SEARCH_TERM_PARAMS = { # 引擎 → referrer URL 里的搜索词参数名(白名单提取)
"Bing": ["q"], "百度": ["wd", "word"], "DuckDuckGo": ["q"], "Yandex": ["text"],
"Ecosia": ["q"], "Yahoo": ["p"], "Brave": ["q"], "Naver": ["query"],
} # 注:Google 不提供,绝不虚构
PAID_CLICK_PARAMS = {"gclid": "Google Ads", "fbclid": "Meta Ads",
"msclkid": "Bing Ads", "yclid": "Yandex Ads"}
SOCIAL_DOMAINS = {
"t.co": "Twitter/X", "twitter.com": "Twitter/X", "x.com": "Twitter/X",
"facebook.com": "Facebook", "linkedin.com": "LinkedIn", "instagram.com": "Instagram",
"vk.com": "VK", "reddit.com": "Reddit", "pinterest.com": "Pinterest",
"telegram.me": "Telegram", "t.me": "Telegram",
}
INAPP_UA_MARKERS = {"MicroMessenger": "微信", "Line/": "Line", "FBAN": "Facebook",
"FBAV": "Facebook", "Instagram": "Instagram", "WhatsApp": "WhatsApp"}
CHANNELS = ("natural_search", "paid_search", "ai_referral", "social",
"in_app", "referral", "direct", "unknown")