takt

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 + the useTakt() hook.
  • @vskstudio/takt-svelte/actions — the use:taktEvent action + init/track… functions re-exported from the core.
  • @vskstudio/takt-svelte/element — the <takt-analytics> web component for plain HTML.
Only <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:

PropTypeDefaultRole
domainstringlocation.hostnameSite identifier
endpointstringhttps://taktlytics.com/api/eventIngestion URL. Pass /api/event for a same-origin first-party proxy.
scriptOriginstringFirst-party origin to derive the endpoint from (the origin followed by /api/event). endpoint wins over it.
outboundbooleanfalseTracks outbound links
filesboolean \| string[]falseTracks downloads (optional extension list)
spabooleantrueTracks client navigation (auto pageviews)
track404booleanfalseReports a 404 event on error pages ([data-takt-404] / <meta name="takt:404"> marker, or a 404 HTTP status).
taggedbooleanfalseAuto-tracks [data-takt-event] elements
respectDntbooleantrueRespects Do Not Track
excludeLocalhostbooleantrueIgnores localhost / private IPs
enabledbooleantrueMaster switch — false disables all tracking
sampleRatenumber1Fraction of sessions to sample (0–1)
trackQuerybooleanfalsePreserves the query string in page URLs
queryParamsstring[]Params preserved when trackQuery is false (allowlist)
excludestring[]Path prefixes never tracked. Segment-bounded: /app matches /app and /app/… but not /application.
scrubUrl(url: string) => stringTransforms each URL before it is sent
The component forwards all of these options to the core: the advanced settings (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 spellings respectdnt and excludelocalhost are still accepted.
  • Values: domain, endpoint, script-origin, enabled, sample-rate, track-query, plus query-params and exclude which 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.