Stickybeak Docs Dashboard Get early access

Frameworks

Qwik

Qwik analytics with Stickybeak starts by adding its script to your rendered pages; this guide shows you where it belongs and how to track page views, goals and purchase revenue.

Add the script

  1. Put your site ID in an environment variable

    Use a PUBLIC_ name, set in .env.production or your host's build settings.

    PUBLIC_STICKYBEAK_SITE_ID=YOUR_SITE_ID
  2. Add the tag next to RouterHead

    import { component$ } from "@builder.io/qwik";
    import { QwikCityProvider, RouterOutlet, ServiceWorkerRegister } from "@builder.io/qwik-city";
    import { RouterHead } from "./components/router-head/router-head";
    
    const siteId = import.meta.env.PUBLIC_STICKYBEAK_SITE_ID;
    
    export default component$(() => {
      return (
        <QwikCityProvider>
          <head>
            <meta charset="utf-8" />
            <RouterHead />
            {siteId && (
              <script
                defer
                data-site={siteId}
                data-domain="example.com"
                src="https://app.usestickybeak.com/_cfw/s.js"
              />
            )}
          </head>
          <body lang="en">
            <RouterOutlet />
            <ServiceWorkerRegister />
          </body>
        </QwikCityProvider>
      );
    });

    Your root.tsx may look a little different depending on the starter and Qwik version. Wherever it renders <head>, the tag goes inside it.

  3. Build and deploy

    In development the variable isn't set, so nothing loads.

Don't run it through Partytown

Leave out type="text/partytown". Partytown runs scripts in a web worker, where Stickybeak can't see the page, its clicks or its route changes.

Check it's working

Test the deployed site, then verify your install.

Track goals

Add data-goal to rendered links or buttons. For other events, use the typed queued helper below. See Custom goals.

<Link href="/signup" data-goal="start_signup" data-goal-plan="pro">Start free trial</Link>
type GoalProps = Record<string, string | number | boolean>;
type Stickybeak = ((goal: string, props?: GoalProps) => void) & { q?: unknown[][] };

declare global {
  interface Window {
    stickybeak?: Stickybeak;
  }
}

export function track(goal: string, props?: GoalProps): void {
  if (typeof window === "undefined") return; // on the server: nothing to do
  if (!window.stickybeak) {
    // Hold calls made before the script loads; it sends them when it arrives.
    const queue: Stickybeak = (...args) => {
      (queue.q ??= []).push(args);
    };
    window.stickybeak = queue;
  }
  window.stickybeak(goal, props);
}
import { component$ } from "@builder.io/qwik";
import { track } from "~/lib/stickybeak";

export const UpgradeButton = component$(() => {
  return (
    <button type="button" onClick$={() => track("upgrade_click", { plan: "pro" })}>
      Upgrade to Pro
    </button>
  );
});

Track purchases

After confirming an order in the browser, send:

window.stickybeak?.("purchase", { revenue: 49, currency: "USD", order_id: "ORDER_ID" });

Use real values; see Revenue.

Page changes

Links, useNavigate(), back and forward count new paths; query-only and hash-only changes do not. See Single-page apps.

If it isn't working

Check the production site ID and domain, then see Troubleshooting.