Install
Add the @v-tilt/browser SDK via npm/pnpm or a script tag in your HTML.
Add the Browser SDK via npm/pnpm or a script tag in your HTML. Both options expose the same window.vt global once init() runs.
#Package manager
npm install @v-tilt/browser#Script tag vs npm
| Install path | Stub needed? | Notes |
|---|---|---|
npm — import { vt } from '@v-tilt/browser' | No | vt is the real SDK. All methods (updateConfig, sendChatMessage, …) exist as soon as your module loads. |
Script tag — inline loader + array.js | Yes | The loader registers a fixed list of method names on window.vt so calls made before array.js finishes loading queue in vt._i and replay on init. |
If you use the script tag and call APIs early (hero CTA → vt.sendChatMessage(), route hook → vt.updateConfig(…)), ensure your snippet includes every method you use. The dashboard Integration Script and Web snippet copy the current list automatically. The canonical set is VTILT_SNIPPET_STUB_METHOD_NAMES in @v-tilt/browser.
#Script tag
For sites without a build step, paste the snippet into your HTML <head>. The snippet creates a stub at window.vt, queues every call, and replaces itself with the full SDK as soon as array.js loads.
<!-- Add to your HTML <head> -->
<script>
!(function (t, e) {
var o, n, p, r
function g(t, e) {
var o = e.split('.')
;(2 == o.length && ((t = t[o[0]]), (e = o[1])),
(t[e] = function () {
t.push([e].concat(Array.prototype.slice.call(arguments, 0)))
}))
}
if (!e.__SV && !(window.vt && window.vt.__loaded)) {
;((window.vt = e),
(e._i = []),
(o =
'init capture identify setUserProperties resetUser getUserIdentity getDeviceId getUserState alias getConfig getSessionId updateConfig setConsent on once off startAutocapture stopAutocapture startSessionRecording stopSessionRecording openChat closeChat toggleChat showChat hideChat sendChatMessage gtag setGoogleUserData'.split(
' ',
)))
for (n = 0; n < o.length; n++) g(e, o[n])
;((e.init = function (i, s, a) {
;(((p = t.createElement('script')).type = 'text/javascript'),
(p.crossOrigin = 'anonymous'),
(p.async = !0),
(p.src = s.script_host
? s.script_host + '/array.js'
: s.api_host + '/dist/array.js'),
(p.onerror = function () {
console.error('vTilt: Failed to load library script:', p.src)
}),
(r = t.getElementsByTagName('script')[0]).parentNode.insertBefore(
p,
r,
))
var u = e
for (
void 0 !== a ? (u = e[a] = []) : (a = 'vt'),
u.toString = function (t) {
var e = 'vt'
return ('vt' !== a && (e += '.' + a), t || (e += ' (stub)'), e)
},
n = 0;
n < o.length;
n++
)
g(u, o[n])
e._i.push([i, s, a])
}),
(e.__SV = 1))
}
})(document, window.vt || [])
vt.init('YOUR_PROJECT_TOKEN', {
api_host: 'https://www.vtilt.com',
})
</script>#Initialise
Call vt.init() once with your project token and config. Any other SDK call before init() is a no-op; calls after are queued and applied in order.
import { vt } from '@v-tilt/browser'
vt.init('YOUR_PROJECT_TOKEN', {
// Optional. https://www.vtilt.com is the managed-cloud ingest host;
// self-hosted or reverse-proxy users replace this with their own origin.
api_host: 'https://www.vtilt.com',
autocapture: true,
capture_pageview: true,
capture_pageleave: true,
persistence: 'localStorage',
})The default snippet loads array.js (core only). Optional features such as chat and session recording lazy-load separate files. See Script bundles to pick array.chat.js, array.full.js, or an npm import variant.
#Update config at runtime
vt.updateConfig(patch) is the single API for changing SDK settings after init(). Pass any subset of the same options you use in init() — autocapture, persistence, chat, and so on. Top-level keys are shallow-merged into the stored config; nested chat is deep-merged so a partial chat patch does not remove other chat fields.
// Toggle autocapture without re-init
vt.updateConfig({ autocapture: false })
// Adjust chat bubble inset on a route change (see [Chat](/docs/browser/chat#bubble-position-and-offset))
vt.updateConfig({
chat: {
bubble: { offset: { bottom: 88, right: 24 } },
},
})
// Combine unrelated changes in one call
vt.updateConfig({
capture_pageview: false,
chat: { greeting: 'Welcome back!' },
})Registered features (chat, session recording, autocapture, …) receive the merged config through the same notification path. An empty patch vt.updateConfig({}) is valid — for example it can re-trigger remote config in a long-lived tab.
#Recommended init options
| Option | Required | Typical value | Why you might change it |
|---|---|---|---|
autocapture | no | true | Disable for highly custom event tracking; pass an object to scope what's captured. |
capture_pageview | no | true | Disable when you handle pageviews manually (e.g. exotic SPA frameworks). |
capture_pageleave | no | true | $pageleave events power engagement metrics — keep on unless you have a reason to drop them. |
persistence | no | localStorage | Use cookie if you need cross-subdomain identity, or memory to disable client-side persistence entirely. |
api_host | no | https://www.vtilt.com | Managed-cloud ingest host. Replace with your own origin if you reverse-proxy or self-host vTilt; omit to fall back to relative URLs (same-origin). |