-
Notifications
You must be signed in to change notification settings - Fork 383
Description
Current library capabilities do not cover embedding app code in third-party websites
Scenario
- api.my-company.com --> serving search results
- www.my-customer.com --> loading some initial JS code (like a searchbar) from api.my-company.com/form
- www.my-customer.com --> .... and dynamically querying api.my-company.com/results
Cookies are increasingly blocked due to:
Safari ITP (Intelligent Tracking Prevention)
Chrome's third-party cookie deprecation
Firefox Enhanced Tracking Protection
In these contexts, Ahoy's current token resolution chain fails to identify visitors:
Ahoy-Visitor/Ahoy-Visit headers → not available / (or we cannot have both tokens)
ahoy_visitor/ahoy_visit cookies → blocked by browser
visitor_token/visit_token params → only when Ahoy.api = true
Generate new UUID → creates a new visitor on every request
This means widget traffic generates a new visitor/visit on every request, making analytics useless.
Current workaround
We implemented a monkeypatch using prepend to inject a fallback token (that we already generate differently) from the controller as token:
module AhoyTrackerFallbackExtension
def existing_visitor_token
super || controller&.try(:fallback_visitor_id)
end
def existing_visit_token
super || controller&.try(:fallback_visitor_id)
end
end
Ahoy::Tracker.prepend(AhoyTrackerFallbackExtension)Our controller stores a session-based ID (from widget SessionStorage) in a fallback_visitor_id field submitted to our API, which Ahoy then uses as a last resort when cookies are unavailable.
Proposed solution
Add a configuration option for custom token resolvers, e.g.:
# Option A: Callback-based
Ahoy.visitor_token_resolver = ->(controller, request) {
controller&.try(:fallback_visitor_id)
}
Use case
Cross-domain tracking where cookies don't work
Any context where the client can provide a stable session ID via params/headers but cookies are blocked, and this session ID is already used in another context than Ahoy (we want to avoid sending them twice in 2 different headers/params)