Client analytics
Verstka sends authored widget events only through GA4 and Yandex Metrica APIs already installed on the page. The viewer does not load or initialize either provider.
interface AnalyticsOptions {
googleMeasurementId?: string
yandexCounterId?: number
}
interface InitOptions {
dev?: boolean
debug?: boolean
viewerUrl?: string
analytics?: false | AnalyticsOptions
}
await initArticle(articleRoot, {
analytics: {
googleMeasurementId: 'G-XXXXXXXXXX',
yandexCounterId: 12345678
}
})
await initArticles(document, {
analytics: {
googleMeasurementId: 'G-XXXXXXXXXX',
yandexCounterId: 12345678
}
})
await initArticles(document, { analytics: false })Resolution and kill switch
For each provider independently, a valid article ID wins; otherwise a valid ID from InitOptions.analytics is used. Article Google plus SDK Yandex therefore attempts both providers. A blank or invalid article value does not block a valid SDK fallback.
analytics: false disables every Verstka-authored call, including persisted article destinations and SDK fallback. It does not disable Enhanced Measurement, click maps, automatic goals, or other observation owned by the site's provider tag.
Repeated initialization of an active root keeps the first options. To apply new options, call its destroy function and initialize that same root again.
Host-installed provider APIs
For Google, the viewer calls only:
gtag('event', eventName, { send_to: measurementId })For Yandex, the viewer first looks for the exact legacy counter and calls yaCounter<ID>.reachGoal(eventName). Only when that exact callable legacy API is absent does it call ym(ID, 'reachGoal', eventName). It does not fall through to ym after attempting legacy, even if the legacy call throws.
V1 does not support Universal Analytics, direct GTM custom-event objects, provider/counter discovery, script loading, config/init, page views, custom parameters, callbacks, retries, or delivery acknowledgement. A GTM-only page must intentionally expose a compatible gtag; adding a duplicate Google tag is not the remedy.
Consent, privacy, and trust
The host site owns its CMP, legal basis, consent order, and provider lifecycle. Configure Google consent defaults before viewer initialization because a visible Show can occur immediately after hydration. Before consent, pass analytics: false; after consent, destroy and reinitialize. Suppressed Once occurrences are not replayed.
Destination IDs are public article JSON. Only trusted publishers may choose them. If article authors must not choose client analytics destinations, the host must pass analytics: false in v1.
Verstka explicitly passes only the event name and destination ID. The site's provider tag can add page URL, referrer, title, device, cookie, consent, identity, and session context. Never include personal data in event names. Keep provider-owned page context current in SPAs. A provider used inside an iframe must exist in that iframe; the viewer never accesses window.parent.
Event and Once behavior
Show is the transition from no positive viewport intersection to a positive intersection after hydration. Hover is mouseenter on the widget root. Click uses a capture listener on the widget root without preventing default behavior or stopping propagation.
Once is page memory keyed by root + widget + trigger + event name. Destroying and reinitializing the same root does not reset it; a replacement root or reload does. No browser storage is used. If a provider is absent during a Once occurrence, there is no later replay. A repeating event can use a provider that becomes callable before a later occurrence.
Yandex goal behavior and limits
reachGoal does not create a goal. Configure a matching JavaScript-event goal or a matching event-ID step in a multi-step goal before expecting a conversion. Automatic goals are separate; their recommended ym-* IDs do not match vrstk_*.
Metrica registers the same goal for one counter no more than once per second, supports up to 200 manual goals, and registers up to 400 online conversions per tag in a Yandex user session. A processed reachGoal is visit activity and can extend the visit. Repeating Hover can therefore create high volume and exhaust the registered-conversion allowance. Do not count a blocked, unmatched, or suppressed call as a registered conversion without provider evidence.
Failure and troubleshooting
A callable global or queued command proves only an attempted call, not provider receipt or registration. Consent, CSP, blockers, or the network can prevent processing. Analytics failure must not break the article.
For GA4, use Tag Assistant and, when you have property access, DebugView. For current Yandex code use ?_ym_debug=2; for previous code use ?_ym_debug=1. Do not claim provider processing without access to the matching property/counter and correlated Events/report evidence.
Mock-client verification
The mock host always passes Google G-2RQ4P9EBVF and Yandex 95333140 as SDK fallback. Ordinary/off mode is fully offline. mockAnalytics=record uses preinstalled doubles and no scripts. mockAnalytics=live is allowed only for the committed client-analytics fixture; production viewer code never installs tags.
Exercise /standard/client-analytics, /feed/client-analytics, and /standard/client-analytics/no-js after:
yarn workspace viewer-core build
yarn workspace renderer build:critical-css
yarn workspace mock-clients test:browserLive mode requires explicit operator opt-in, authorized dedicated non-production destinations, disabled GA Enhanced Measurement, disabled Yandex Automatic goals and unrelated collection, preflighted filters, and no personal data. A console call alone does not prove a registered conversion.