Product

Session Replay and Heatmaps for Svelte and SvelteKit

Add session replay and heatmaps to a Svelte or SvelteKit application. Covers placing the loader in app.html, client-side navigation, identifying users, tracking events from the browser only, and masking.

Purushottam Kumar Suman
Purushottam Kumar SumanSeptember 21, 20265 min read
Founder & CEO, DeepSync
SvelteKit project code with analytics setup

Short answer: in SvelteKit, add the loader script tag to src/app.html, after %sveltekit.head%. In a plain Svelte app built with Vite, add it to index.html. Client-side navigation is recorded automatically. Call identify and track from browser-only code, and add masking classes to elements that show personal data.

Table of Contents

  1. SvelteKit
  2. Svelte With Vite
  3. Navigation
  4. Calling the SDK Safely
  5. Masking
  6. Things to Check
  7. Key Takeaways

SvelteKit

app.html is the template every page is rendered into, so a tag placed there is on every page and loads once.

<!-- src/app.html -->
<head>
  %sveltekit.head%
  <script async src="YOUR_LOADER_URL"></script>
</head>

Your loader URL is in the project's install settings. Reference: Install in Angular, Svelte, or SvelteKit.

This works the same for server-rendered, prerendered, and client-rendered routes. The recorder runs in the browser on the final DOM.

Svelte With Vite

For a client-only Svelte app, add the same tag to the project's index.html:

<head>
  <script async src="YOUR_LOADER_URL"></script>
</head>

SvelteKit's router uses the History API for client-side navigation. The SDK patches it, so each navigation becomes a page view in session timelines, heatmaps, and funnels. No afterNavigate hook is needed.

For interface changes that do not alter the URL, such as steps in a form, track an event.

Calling the SDK Safely

SvelteKit runs your code on the server as well as in the browser. The SDK exists only in the browser, so guard your calls.

import { browser } from "$app/environment";

export function track(event, props) {
  if (browser && typeof window.deepsync === "function") {
    window.deepsync("track", event, props);
  }
}

export function identify(id, traits) {
  if (browser && typeof window.deepsync === "function") {
    window.deepsync("identify", id, traits);
  }
}

Identify once the user is known, from a layout or after login:

identify(user.id, { plan: user.plan });

Track confirmed outcomes:

track("checkout_completed", { value: 2499, currency: "INR" });

If a call can happen before the loader finishes, add the command-queue stub from how the SDK works to app.html above the loader, so early calls are held and sent once the SDK is ready.

See the SDK API for all calls.

Masking

Inputs, passwords, and payment fields are masked by default. Add classes for rendered content:

<p class="ds-mask">{customer.phone}</p>

<div class="ds-block">
  <StatementTable rows={statement} />
</div>

Svelte's scoped styles do not interfere. The recorder reads the class from the DOM (PII masking).

In consent-required mode, which is the default, send the consent signal from your cookie banner (consent modes).

Things to Check

  • Transitions. Svelte's transition: directives animate elements in. A recording may briefly show the starting state. If content appears missing in replay, check for an entrance animation (capture limits).
  • Prerendered pages. These are static HTML. The tag in app.html is included, so they are recorded.
  • Form actions. SvelteKit form actions with progressive enhancement submit without a full reload. Track success as an event from the action's result.
  • Hydration gap. Server-rendered pages are visible before they are interactive. Dead clicks in that window are worth noticing.
  • Content Security Policy. If you configure one, allow the ingest origin in script-src and connect-src (CSP guide).
  • Preview deployments. Avoid recording preview and staging builds in your production project (excluding internal traffic).

Key Takeaways

  • One script tag in src/app.html.
  • Navigation is tracked automatically.
  • Guard SDK calls so they run only in the browser.
  • Mask rendered personal data with a class.

Conclusion

SvelteKit setup is one line in one file. After that, the work is deciding what to mask and which outcomes to track.

Start free · Install in SvelteKit

Frequently Asked Questions

Was this article helpful?

Ready to understand
users like never before?

Join thousands of teams who use DeepSync to uncover insights,improve experiences, and build better products—faster.

Quick & easy onboarding
See results in real time
Enterprise-grade security