> ## Documentation Index
> Fetch the complete documentation index at: https://ihub.learnille.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Beacon Analytics Architecture

> Migrated from the previous Learnille internal documentation hub

## Overview

The Beacon Analytics system tracks user engagement across the Learnille marketplace. It captures impressions, clicks, and bounces for courses, consultations, instructors, and consultants to power analytics dashboards and recommendation algorithms.

**Design Principles:**

* Privacy-conscious with obfuscated endpoints
* Minimal payload size for performance
* Resilient with fallback mechanisms
* Deduplicated at client and server level

***

## System Architecture

```
┌─────────────────────────────────────────────────────────────────┐
│                         Frontend (Next.js)                       │
├─────────────────────────────────────────────────────────────────┤
│  BeaconWrapper          │  useBounceTracker    │  beacon.ts     │
│  - IntersectionObserver │  - Time tracking     │  - BeaconQueue │
│  - Impression on 50%    │  - <10s = bounce     │  - HMAC signing│
│    visibility           │  - pagehide event    │  - Batching    │
└─────────────────────────┴──────────────────────┴────────────────┘
                                    │
                          ┌─────────▼─────────┐
                          │   Masked API      │
                          │   /v1/a/s (init)  │
                          │   /v1/a/c (batch) │
                          │   /v1/a/t.gif     │
                          └─────────┬─────────┘
                                    │
┌───────────────────────────────────▼─────────────────────────────┐
│                         Backend (NestJS)                         │
├─────────────────────────────────────────────────────────────────┤
│  BeaconController       │  BeaconService      │  BeaconGuard    │
│  - Session init         │  - Token generation │  - HMAC verify  │
│  - Batch processing     │  - Signature verify │  - Rate limit   │
│  - Pixel fallback       │  - Event processing │                 │
└─────────────────────────┴─────────┬───────────┴─────────────────┘
                                    │
                    ┌───────────────┼───────────────┐
                    ▼               ▼               ▼
              ┌─────────┐    ┌───────────┐   ┌────────────┐
              │  Redis  │    │ PostgreSQL│   │ Impression │
              │  - Rate │    │ - Storage │   │  Service   │
              │  - Dedup│    │           │   │            │
              └─────────┘    └───────────┘   └────────────┘
```

***

## Event Types

| Code | Type | Description |
| - | - | - |
| `i` | Impression | Item visible in viewport (50%, 150ms) |
| `k` | Click | User clicks on item |
| `b` | Bounce | User leaves detail page within 10 seconds |

***

## Entity Types

| Code | Entity |
| - | - |
| `c` | Course |
| `n` | Consultation |
| `i` | Instructor |
| `o` | Consultant |

***

## API Endpoints

All endpoints are intentionally obfuscated for security.

| Endpoint | Method | Purpose |
| - | - | - |
| `/v1/a/s` | GET | Initialize session token |
| `/v1/a/c` | POST | Collect batch of events |
| `/v1/a/t.gif` | GET | Pixel fallback (1x1 GIF) |

***

## Payload Structure

### Session Init Response

```json theme={null}
{
  "t": "session-token-jwt",
  "k": "hmac-signing-key"
}
```

### Batch Request

```json theme={null}
{
  "t": "session-token",
  "b": [
    {
      "d": "base64-encoded-payload",
      "ts": 1705312345678,
      "n": "random-nonce",
      "sig": "hmac-sha256-signature"
    }
  ]
}
```

### Decoded Payload (`d` field)

```json theme={null}
{
  "t": "c",           // Entity type (course)
  "e": "uuid",        // Entity ID
  "v": "i",           // Event type (impression)
  "r": "referrer",    // Document referrer
  "f": "fingerprint", // Browser fingerprint
  "s": "session-id",  // Client session ID
  "ss": "search-sid", // Search session ID (optional)
  "q": "query",       // Search query (optional)
  "rid": "result-id", // Search result ID (optional)
  "val": 1,           // Value (optional)
  "u": "user-id"      // User ID if logged in (optional)
}
```

***

## Security Features

### Authentication

* Session tokens generated server-side (JWT, 24h expiry)
* HMAC-SHA256 signing key issued per session
* All batch requests validated by BeaconGuard

### Replay Protection

* Nonce included in each event
* Timestamp validated (±30 second window)
* Signature covers: payload + timestamp + nonce + token

### Rate Limiting

* 50 requests per 5 minutes per IP (Redis-backed)
* Prevents abuse and spam events

### Deduplication

* **Client-side:** Cookie + sessionStorage tracking
* **Server-side:** Redis with composite key (user/IP + entity + event type)
* TTL: 30 days for cookies, session duration for storage

***

## Data Flow

1. **Page Load**
   * BeaconQueue restores session from sessionStorage
   * If no session, fetches new token from `/v1/a/s`
   * BeaconWrapper registers IntersectionObserver on cards

2. **Impression Tracking**
   * Item becomes 50% visible for 150ms
   * `trackImpression()` called with entity type and ID
   * Client checks dedup (cookie/sessionStorage)
   * Event queued in BeaconQueue

3. **Batching**
   * Events accumulate (max 10 or 2s timeout)
   * Each event signed with HMAC-SHA256
   * Batch sent to `/v1/a/c`

4. **Server Processing**
   * BeaconGuard validates session token
   * BeaconService verifies each event signature
   * Checks Redis for duplicates
   * ImpressionService writes to PostgreSQL

5. **Page Unload**
   * `navigator.sendBeacon()` flushes remaining events
   * Falls back to pixel if sendBeacon fails

***

## Frontend Components

### beacon.ts

Core tracking service with BeaconQueue class.

**Key Functions:**

* `trackImpression(entityType, entityId, metadata?)` - Track view
* `trackClick(entityType, entityId, metadata?)` - Track click
* `trackBounce(entityType, entityId)` - Track early exit

**BeaconQueue:**

* Manages session token lifecycle
* Batches events with configurable thresholds
* Signs payloads with HMAC-SHA256
* Handles flush on page unload

### BeaconWrapper.tsx

React component that wraps marketplace cards.

**Props:**

* `entityType` - Course, consultation, etc.
* `entityId` - UUID of the entity
* `metadata` - Optional tracking metadata

**Behavior:**

* Uses IntersectionObserver (50% threshold, 150ms delay)
* Tracks impression when visible
* Tracks click on interaction

### useBounceTracker.ts

React hook for detail pages.

**Usage:**

```tsx theme={null}
useBounceTracker('course', course?.id);
```

**Behavior:**

* Records page entry time
* On pagehide/beforeunload, if \< 10s elapsed, sends bounce event

***

## Backend Components

### BeaconController

NestJS controller at `/v1/a`.

**Endpoints:**

* `GET /s` - Initialize session
* `POST /c` - Process batch (guarded)
* `GET /t.gif` - Pixel fallback

### BeaconService

Core business logic.

**Methods:**

* `initializeSession()` - Generate token + signing key
* `verifySessionToken(token)` - Validate JWT
* `processBatch(dto, ip, userAgent)` - Process events
* `processItem(item, ip, userAgent)` - Verify and forward to ImpressionService

### BeaconGuard

Request validation guard.

**Checks:**

* Token presence
* Token validity (JWT verification)
* Rate limiting

***

## Related Files

### Frontend

* `public/src/services/beacon.ts`
* `public/src/components/BeaconWrapper.tsx`
* `public/src/hooks/useBounceTracker.ts`
* `public/src/hooks/useBeacon.ts`

### Pages with Tracking

* `public/src/pages/course/[slug].tsx` - Course detail (impression + bounce)
* `public/src/pages/consultation/[slug]/index.tsx` - Consultation detail (impression + bounce)
* `public/src/pages/instructor/[id].tsx` - Instructor profile (impression + bounce)
* `public/src/pages/consultant/[id].tsx` - Consultant profile (impression + bounce)

### Tab Sections with Tracking

* `public/src/sections/course/Instructor.tsx` - Instructor tab on course page
* `public/src/sections/consultation/Consultant.tsx` - Consultant tab on consultation page

### Card Collections with Tracking

* `public/src/components/instructor/SimilarInstructors.tsx` - Instructor cards in swiper
* `public/src/components/consultant/SimilarConsultants.tsx` - Consultant cards in swiper

### Backend

* `server/src/impression/beacon.controller.ts`
* `server/src/impression/beacon.service.ts`
* `server/src/impression/guards/beacon.guard.ts`
* `server/src/impression/dto/beacon.dto.ts`
* `server/src/impression/impression.service.ts`

***

## Related ADRs

* [ADR 008: Beacon Analytics - Direct Database Writes](https://ihub.learnille.com/engineering/architecture/architecture-decision-records.md#adr-008-beacon-analytics---direct-database-writes)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.