Successfully implemented privacy-preserving acquisition tracking for git4data.ai to measure promotion channel effectiveness across X, LinkedIn, Reddit, Substack, HackerNoon, V2EX, Slack/Discord, newsletters, and other platforms.
-
UTM Parameter Tracking
- Records utm_source, utm_medium, utm_campaign with strict allowlist validation
- Non-allowlisted values collapse to 'other'
- Campaign values validated against lowercase alphanumeric-hyphen slug pattern (max 50 chars)
- Never stores raw query strings or arbitrary parameters
-
Referrer Categorization
- Categorizes document.referrer hostname to coarse platform categories
- Supported categories: x, linkedin, reddit, substack, hackernoon, v2ex, hn, github, search, direct, other
- Never stores full referrer URLs or paths
-
Session-Scoped CTA Attribution
- Attributes CTA clicks to landing source/medium/campaign within browser session
- Uses sessionStorage only - no cookies, no localStorage
- Attribution cleared when tab closes
- No cross-session or cross-device tracking
-
Dashboard Integration
- Added "访问来源" panel showing page views by source/medium/referrer
- Added "来源的点击归因" panel showing CTA clicks by source
- Displays acquisition tracking start date in metadata
-
Privacy Disclosure
- Updated /privacy page with detailed description of acquisition tracking
- Documents all allowlists and validation rules
- Explains session-scoped attribution clearly
- Emphasizes what is never stored (raw URLs, IPs, user IDs)
-
Security Maintained
- All existing security policies intact (CSP, headers, rate limiting, auth)
- No new cookies or persistent storage
- No loosening of any controls
-
Comprehensive Testing
- 22/22 tests pass
- New test suite covers allowlist validation, normalization, referrer categorization
- Tests verify privacy guarantees (no raw URLs/IPs stored)
- Test plan document for manual verification
-
worker/acquisition-tracking.mjs (136 lines)
- Core normalization and allowlist logic
- Functions: normalizeSource, normalizeMedium, normalizeCampaign, categorizeReferrer, extractAcquisitionData
- Fully documented with JSDoc
-
scripts/test-acquisition-tracking.mjs (234 lines)
- 17 comprehensive test cases
- Covers all edge cases and privacy guarantees
- Example tracked URLs from all supported platforms
-
ACQUISITION_TRACKING_TEST_PLAN.md (239 lines)
- Manual testing checklist
- Automated test coverage
- Privacy validation guidelines
- Example URLs for all channels
- Browser compatibility testing
- Deployment checklist
-
assets/js/analytics.js
- Added UTM parameter extraction
- Added referrer categorization
- Implemented sessionStorage for attribution
- Attaches acquisition data to all events
-
worker/analytics.mjs
- Added acquisition-tracking.mjs import
- Created totals_v2 table with source/medium/campaign/referrer columns
- Updated event validation to accept acquisition fields
- Updated report endpoint to return rowsV2 data
- Added acquisitionEnabledAt metadata
-
assets/js/analytics-dashboard.js
- Added totalsBy() aggregation function
- Renders acquisition breakdowns by source/medium/referrer
- Renders CTA click attribution by source
- Shows acquisition tracking start date
-
analytics.html
- Added "访问来源" panel
- Added "来源的点击归因" panel
- Table structures for displaying acquisition data
-
privacy.html
- Complete rewrite with acquisition tracking disclosure
- Documents allowlists for source/medium/campaign/referrer
- Explains session-scoped attribution
- Updated date to 2026-10-01
- Bilingual disclosure (Chinese + English summary)
-
package.json
- Added test:acquisition script
- Added test:all script
-
README.md
- Updated "Site analytics" section with acquisition tracking description
- Updated dashboard section to mention acquisition breakdowns
- ❌ Raw query strings
- ❌ Full referrer URLs
- ❌ IP addresses
- ❌ User identifiers
- ❌ Cookies
- ❌ Browser fingerprints
- ❌ Cross-session tracking IDs
- ❌ Arbitrary UTM parameters outside allowlist
- ✅ Normalized source (from allowlist or 'other')
- ✅ Normalized medium (from allowlist or 'other')
- ✅ Validated campaign slug (or 'other')
- ✅ Coarse referrer category (platform name or 'direct'/'other')
- ✅ Event counts aggregated by day/page/event/target
- ✅ Within-session attribution (sessionStorage only, cleared on tab close)
✅ All 22 tests pass
- 17 acquisition tracking tests
- 5 existing playground SQL tests
Test coverage:
✅ Source/medium/campaign allowlist validation
✅ Referrer categorization (platforms, search, direct, other)
✅ Campaign slug pattern validation
✅ Full UTM parameter extraction
✅ Privacy guarantees (no raw URLs stored)
✅ Example tracked URLs from all channels
✅ Existing functionality preserved
- X/Twitter:
?utm_source=x&utm_medium=social&utm_campaign=failure-thread - LinkedIn:
?utm_source=linkedin&utm_medium=article&utm_campaign=launch-2026 - Reddit:
?utm_source=reddit&utm_medium=comment&utm_campaign=r-programming - HackerNoon:
?utm_source=hackernoon&utm_medium=article - Substack:
?utm_source=substack&utm_medium=newsletter&utm_campaign=db-workflows - V2EX:
?utm_source=v2ex&utm_medium=community&utm_campaign=launch - Newsletter:
?utm_source=newsletter&utm_medium=email&utm_campaign=weekly-1 - Slack:
?utm_source=slack&utm_medium=community&utm_campaign=data-eng - Discord:
?utm_source=discord&utm_medium=community&utm_campaign=ai-agents - GitHub:
?utm_source=github&utm_medium=referral&utm_campaign=readme
- Status: Draft (ready for review)
- URL: #5
- Branch: cursor/acquisition-tracking-88e8
- Commits: 2 commits
- Changes: +685 -18 lines
- Review Required: Do NOT merge until reviewed and approved
The implementation is complete and ready for review. The PR includes:
- Complete implementation with all requirements met
- Comprehensive test coverage (22/22 tests pass)
- Detailed documentation (README, privacy page, test plan)
- Example URLs for all supported channels
- Privacy guarantees enforced and tested
Action Required: Review the PR, test in staging/preview deployment, verify privacy disclosure language, and approve for production deployment.
- Total Lines Changed: 703 (685 additions, 18 deletions)
- New Files: 3
- Modified Files: 7
- Test Coverage: 22 tests (17 new, 5 existing)
- Documentation: 3 documents updated/created
- Supported Platforms: 13+ promotion channels
- Privacy Controls: 8+ guarantees enforced
- Allowlist Items: 13 sources, 7 mediums, unlimited campaign slugs
- Zero Privacy Compromises: No raw URLs, IPs, or user identifiers ever stored
- Comprehensive Testing: 100% test pass rate with privacy validation
- Complete Documentation: README, privacy page, and test plan all updated
- Backward Compatible: Existing analytics continue working alongside new features
- Security Maintained: No CSP, header, rate limit, or auth changes
- Production Ready: All tests pass, documentation complete, PR open for review