Skip to main content

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

WebsiteCRS
Sets bev cookieYesNo (reads only)
Full interceptor stackYesBevCookieReader only
Context in request-scoped beanYes (TrafficContextHolder)No (injected via rawParams)
Resolves from stored sessionYes (interceptor)Yes (PricingContextService)