Skip to main content

1. Overview

This document defines the Product Requirements for a secure, tamper-resistant impression tracking system for Learnille’s marketplace. The system tracks course and consultation visibility, enables instructor/consultant analytics, and supports relevance ranking.

2. Goals

Primary Goals

  • Track true impressions: product actually appears in user viewport
  • Maintain tamper-resistant impression signals via HMAC signing
  • Provide accurate session-level deduping and per-product metrics
  • Support obfuscated endpoints to prevent competitor detection

Secondary Goals

  • Enable instructor/consultant dashboards (impressions, CTR, referrers)
  • Support ML/relevance ranking via impression data
  • Allow anti-fraud heuristics (velocity, bot detection)

3. Non-Goals

  • No external analytics vendor integration
  • No third-party fingerprinting SDK
  • No cookie consent requirements (privacy-first approach)
  • No real-time streaming infrastructure at initial stage

4. Architecture Overview

Initial Phase

Future Upgrade Path

  • TimescaleDB: Convert impressions table to a hypertable for efficient time-series partitioning and faster aggregation queries (e.g., time_bucket).

5. Client-Side Requirements

5.1 Impression Trigger

Use browser IntersectionObserver to record an impression only when:
  1. Product card enters viewport
  2. Remains visible ≥ 150ms
  3. Impression for (entity_id + session_id) has not been fired this session

5.2 Required Client Fields

5.3 Legitimacy Verification (Handshake)

To ensure requests are absolutely legitimate and “authorized” by the server without user login: 1. Handshake Phase
  • Client calls GET /api/v1/beacon/h.
  • Server verifies client (IP reputation, standard headers).
  • Server returns a Signed Session Token (JWT-like) containing:
    • session_id
    • issued_at
    • expiry (e.g., 2 hours)
  • Token is signed with BEACON_PRIVATE_KEY.
2. Signing Phase Client signs each impression batch using:
  • BEACON_SESSION_SECRET is derived from the session token or a shared secret.
  • Server verifies both the Session Token signature and the Impression HMAC.
This “double-seal” ensures:
  • The client was initialized by our server.
  • The payload hasn’t been tampered with.
  • Replay attacks are impossible (even if signature is stolen, it’s tied to an expired token).

5.4 Payload Obfuscation

All fields use short codes to obscure intent: Entity types use codes: c=course, n=consultation, i=instructor, o=consultant

6. Session Requirements

6.1 Browser Session ID

  • Stored in sessionStorage (not cookies)
  • Value: UUIDv4
  • Expires when tab closes
  • Key: bkn_sid

6.2 Deduplication

  • Track fired impressions in sessionStorage
  • Key format: bkn:{entity_type}:{entity_id}
  • Prevents duplicate tracking per session

6.3 Device Fingerprint

Minimal fingerprint using:
  • User agent
  • Screen resolution
  • Timezone offset
  • Language
Hash via: SHA256(ua + screen + tz + lang).substring(0, 16)

6.4 Client-Side Batching

To improve performance and reduce server load:
  • Queue: Store impressions in a memory queue.
  • Flush Triggers:
    • Time: Every 2 seconds.
    • Size: Every 10 queued items.
    • Event: pagehide / beforeunload (using navigator.sendBeacon).
  • Format: Batch array sent to single endpoint.

7. Server Endpoint Specification

7.1 HTTP (Handshake)

Returns: { "token": "signed.session.token", "key": "temporary-signing-key" }

7.2 HTTP (Batch)

Request Body:

7.3 HTTP (Pixel Fallback)

(Unchanged: Single request via px.gif)

8. Attribution (“The Golden Thread”)

To track conversion value back to impressions:

8.1 Search Session Correlation

  • Generate search_session_id on search execution.
  • Store search_session_id in sessionStorage for persistence across the search results page.
  • Pass search_session_id to:
    1. Impression payload (ss field).
    2. Product URL (query param ?sid=...).

8.2 Checkout Association

  • The useBeacon hook captures sid from the URL on product detail pages and saves it to sessionStorage (key: search_session_id).
  • On Order creation, the frontend sends this search_session_id to the backend.
  • The Order entity persists searchSessionId.
  • Analytics: Join orders table with impressions via search_session_id to calculate “Revenue per Search” and “Conversion Rate by Rank”.

9. Dedupe Logic

8.1 Client-Side Dedupe

Per session, per entity:

8.2 Server-Side Dedupe

Redis-based with 1-hour TTL:
Uses SET NX (set-if-not-exists) for atomic deduplication.

9. Database Schema

impressions

Metadata JSONB

Stores owner IDs for filtering:

10. Analytics Queries

Impressions by Period

CTR Calculation

Instructor Dashboard


11. Fraud & Abuse Detection

Early Indicators

Future Upgrades

  • Browser behavior scoring
  • ML-based anomaly detection
  • Scroll velocity analysis

12. Operational Requirements

12.1 Performance

  • API handles ≥500 req/sec
  • ≤15ms average response time
  • Redis for hot-path operations

12.2 Security

  • Rotate BEACON_SECRET every 90 days
  • Enforce TLS
  • Limit body size to 4KB
  • Rate-limit by IP/session

12.3 Monitoring

  • Track rejection rate by reason
  • Alert on >5% signature failures
  • Log suspicious patterns

13. Client SDK Requirements

useBeacon Hook

beacon Function

  • Generate/maintain session ID
  • Sign events with HMAC
  • Fallback to pixel if fetch blocked
  • Batch send (via BeaconQueue)

14. Success Metrics


15. Environment Variables


16. File Structure


17. Implementation Phases

Phase 1: Core (Week 1)

  • BeaconController with endpoints
  • BeaconGuard with HMAC validation
  • Frontend beacon.ts service
  • useBeacon hook
  • Integration on course/consultation pages

Phase 2: Security (Week 2)

  • Timestamp validation
  • Nonce tracking in Redis
  • Rate limiting
  • Behavioral detection

Phase 3: Analytics (Week 3)

  • Dashboard API endpoints
  • Aggregation queries
  • Instructor/consultant views

18. Open Questions

  1. Should we track scroll depth for engagement scoring?
  2. Should impressions be versioned for ranking model training?
  3. Should we implement A/B testing for different CTR thresholds?

19. Next Steps

  1. ✅ Approve PRD
  2. Generate API contract
  3. Generate NestJS implementation
  4. Generate JS client SDK
  5. Deploy MVP
  6. Add monitoring & alerts