In this section

Resources / Installation / Frameworks

Install Hubbo in Svelte and SvelteKit

Add the embed snippet to app.html in SvelteKit or index.html in a plain Svelte app.

Svelte apps ship an HTML shell, which is the best place for the Hubbo snippet.

SvelteKit

Edit src/app.html and add the snippet inside <head>, before %sveltekit.head% or after it:

<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <script src="https://api.hubbo.io/embed?key=ACCOUNT_KEY" id="hubbo-embed-script" async type="module" crossorigin="use-credentials"></script>
    %sveltekit.head%
  </head>
  <body data-sveltekit-preload-data="hover">
    <div style="display: contents">%sveltekit.body%</div>
  </body>
</html>

Plain Svelte (Vite)

Open index.html in the project root (or public/index.html in older templates) and add the snippet inside <head>.

<script src="https://api.hubbo.io/embed?key=ACCOUNT_KEY" id="hubbo-embed-script" async type="module" crossorigin="use-credentials"></script>

Loading from a layout component

You can also load the script from your root layout in the browser only:

<script>
  import { onMount } from 'svelte';

  let { children } = $props();

  onMount(() => {
    if (document.getElementById('hubbo-embed-script')) return;

    const script = document.createElement('script');
    script.src = 'https://api.hubbo.io/embed?key=ACCOUNT_KEY';
    script.type = 'module';
    script.async = true;
    script.crossOrigin = 'use-credentials';
    script.id = 'hubbo-embed-script';
    document.body.appendChild(script);
  });
</script>

{@render children()}

Client-side routing

SvelteKit navigates without a full reload. That is fine, the script stays loaded and notification, NPS and survey URL rules follow the browser location (History API + polling).

Svelte 4 layouts

If you are still on Svelte 4 / older SvelteKit, use <slot /> instead of {@render children()} and drop the $props() line.