How Traffic Context Works
Initial Visit (with params)
GET /home?partner_id=VISA&utm_source=visa_campaign
1. BevCookieInterceptor → sets bev=1712345_abcdef (1-year cookie)
2. TrafficContextInterceptor:
a. Reads partner_id=VISA from query params
b. Classifies traffic: PARTNER
c. Persists visitor_session row in PostgreSQL
d. Caches in Redis (7-day TTL) + Caffeine (5-min TTL)
e. Populates TrafficContextHolder for this request
3. All downstream APIs use the context automatically
Return Visit (no params)
GET /home
(browser sends bev cookie automatically)
1. BevCookieInterceptor → reads existing bev=1712345_abcdef
2. TrafficContextInterceptor:
a. No fresh params in query string
b. Looks up bev in cache: L1 (Caffeine) → L2 (Redis) → DB
c. Finds VISA session from 2 days ago (within 7-day TTL)
d. Populates TrafficContextHolder with VISA context
3. Same personalized experience as initial visit
Context Override
Day 1: GET /home?partner_id=VISA → VISA context stored
Day 3: GET /home?partner_id=HDFC → HDFC overrides VISA
Day 5: GET /home → HDFC context resolved
Day 15: GET /home → TTL expired → default experience
Fresh params always override stored context. Latest context wins.
Context Expiry
Configurable via traffic.context.ttl-days (default: 7).
After TTL expires with no new visit from that source → default experience (no filtering, all offers shown).
CRS vs Website
| Website | CRS | |
|---|---|---|
| Sets bev cookie | Yes | No (reads only) |
| Full interceptor stack | Yes | BevCookieReader only |
| Context in request-scoped bean | Yes (TrafficContextHolder) | No (injected via rawParams) |
| Resolves from stored session | Yes (interceptor) | Yes (PricingContextService) |