Svelte
Svelte has a dedicated wrapper: @vskstudio/takt-svelte (component, action, web component), built on the @vskstudio/takt-core core.
The core is a peer dependency: install both packages.
pnpm add @vskstudio/takt-svelte @vskstudio/takt-core
# or: npm install @vskstudio/takt-svelte @vskstudio/takt-core
# or: yarn add @vskstudio/takt-svelte @vskstudio/takt-core
# or: bun add @vskstudio/takt-svelte @vskstudio/takt-core The package exposes three integration styles:
@vskstudio/takt-svelte— the<Takt>component + theuseTakt()hook.@vskstudio/takt-svelte/actions— theuse:taktEventaction +init/track… functions re-exported from the core.@vskstudio/takt-svelte/element— the<takt-analytics>web component for plain HTML.
<Takt> and <takt-analytics> are SSR-safe: they initialize on mount, in the browser. The init() from the /actions subpath touches history as soon as it is called — running it in a SvelteKit component's <script> executes it during server rendering and throws ReferenceError: history is not defined. Call it from onMount.This page is the option reference. For the end-to-end integration in a SvelteKit app and its main trap — useTakt() called in a component’s <script>, hence before <Takt> mounts — see the guide cookieless analytics in a SvelteKit app.
<Takt> component + useTakt()
Place <Takt> once (typically in +layout.svelte): it initializes the instance on mount, emits the initial pageview and wires up SPA navigation. The component renders no markup — it is a wiring point, not a container, so it has no children. useTakt() retrieves the instance from anywhere in the app (a module store acts as the relay), not only below <Takt>.
<!-- +layout.svelte -->
<script>
import { Takt } from '@vskstudio/takt-svelte'
</script>
<Takt domain="example.com" outbound files />
<slot /> Call useTakt() inside the handler, not in the <script>: the <script> runs at component init, hence before <Takt>’s onMount. An instance captured there would be the permanent no-op, and every event would go nowhere.
<script>
import { useTakt } from '@vskstudio/takt-svelte'
</script>
<button onclick={() => useTakt().track('Signup', { props: { plan: 'pro' } })}>
Sign up
</button>
<button
onclick={() =>
useTakt().track('Purchase', {
props: { plan: 'pro' },
revenue: { amount: '29', currency: 'EUR' }
})}
>
Buy
</button> <Takt> component props:
| Prop | Type | Default | Role |
|---|---|---|---|
domain | string | location.hostname | Site identifier |
endpoint | string | https://taktlytics.com/api/event | Ingestion URL. Pass /api/event for a same-origin first-party proxy. |
scriptOrigin | string | — | First-party origin to derive the endpoint from (the origin followed by /api/event). endpoint wins over it. |
outbound | boolean | false | Tracks outbound links |
files | boolean \| string[] | false | Tracks downloads (optional extension list) |
spa | boolean | true | Tracks client navigation (auto pageviews) |
track404 | boolean | false | Reports a 404 event on error pages ([data-takt-404] / <meta name="takt:404"> marker, or a 404 HTTP status). |
tagged | boolean | false | Auto-tracks [data-takt-event] elements |
respectDnt | boolean | true | Respects Do Not Track |
excludeLocalhost | boolean | true | Ignores localhost / private IPs |
enabled | boolean | true | Master switch — false disables all tracking |
sampleRate | number | 1 | Fraction of sessions to sample (0–1) |
trackQuery | boolean | false | Preserves the query string in page URLs |
queryParams | string[] | — | Params preserved when trackQuery is false (allowlist) |
exclude | string[] | — | Path prefixes never tracked. Segment-bounded: /app matches /app and /app/… but not /application. |
scrubUrl | (url: string) => string | — | Transforms each URL before it is sent |
enabled, sampleRate, trackQuery, queryParams, exclude, scrubUrl) are available as props, without going through the /actions subpath. Only debug is not exposed.useTakt() does not throw: called before <Takt> mounts or during SSR, it returns a no-op instance — and warns once in the console (useTakt() called before <Takt /> mounted). That message is the symptom of the trap above.
use:taktEvent action
Without a component, initialize yourself via init(), then attach taktEvent to a clickable element. init() must be called from onMount: at the <script> top level it would run during server rendering and throw ReferenceError: history is not defined.
<script>
import { onMount } from 'svelte'
import { init, taktEvent } from '@vskstudio/takt-svelte/actions'
onMount(() => init({ domain: 'example.com', sampleRate: 0.5, trackQuery: false }))
</script>
<button use:taktEvent={{ name: 'Signup', props: { plan: 'pro' } }}>
Sign up
</button>
<button use:taktEvent={{ name: 'Purchase', revenue: { amount: '29', currency: 'EUR' } }}>
Buy
</button> The action is reactive: if the parameters change, later clicks use the new values. The listener is removed when the element is destroyed.
<takt-analytics> web component
For plain HTML or a non-Svelte framework, import the (auto-registered) element:
<script type="module">
import '@vskstudio/takt-svelte/element'
</script>
<takt-analytics domain="example.com" outbound files></takt-analytics> Attributes mirror the props:
- Flags (presence = on, value ignored):
outbound,files,track-404,tagged. - On by default, set
="false"to turn them off:spa,respect-dnt,exclude-localhost. The historical single-word spellingsrespectdntandexcludelocalhostare still accepted. - Values:
domain,endpoint,script-origin,enabled,sample-rate,track-query, plusquery-paramsandexcludewhich take a comma-separated list.
files takes no extension list here, and scrubUrl has no equivalent: those are functions and arrays the Svelte component receives as props, out of reach of an HTML attribute.