Stickybeak Docs Dashboard Get early access

Frameworks

SolidStart

SolidStart 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

    A VITE_ variable is available in server code through import.meta.env. Set it in .env.production or your host's build settings.

    VITE_STICKYBEAK_SITE_ID=YOUR_SITE_ID
  2. Add the tag to the document

    // @refresh reload
    import { createHandler, StartServer } from "@solidjs/start/server";
    
    const siteId = import.meta.env.VITE_STICKYBEAK_SITE_ID;
    
    export default createHandler(() => (
      <StartServer
        document={({ assets, children, scripts }) => (
          <html lang="en">
            <head>
              <meta charset="utf-8" />
              <meta name="viewport" content="width=device-width, initial-scale=1" />
              {assets}
              {siteId && (
                <script
                  defer
                  data-site={siteId}
                  data-domain="example.com"
                  src="https://app.usestickybeak.com/_cfw/s.js"
                />
              )}
            </head>
            <body>
              <div id="app">{children}</div>
              {scripts}
            </body>
          </html>
        )}
      />
    ));
  3. Build and deploy

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

Solid with Vite, without SolidStart

Paste the standard snippet into index.html before </head>, as a plain <script> (not type="module"):

Paste the same plain script tag before </head> in root index.html; do not add type="module".

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.

<A href="/signup" data-goal="start_signup" data-goal-plan="pro">Start free trial</A>
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 { createSignal } from "solid-js";
import { track } from "~/lib/stickybeak";

export default function Counter() {
  const [count, setCount] = createSignal(0);

  function increment() {
    setCount(count() + 1);
    if (count() === 10) track("counter_reached_10");
  }

  return (
    <button type="button" onClick={increment}>
      Clicked {count()} times
    </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, navigate(), back and forward count new paths. Replace, query-only, hash-only and <HashRouter> changes do not. See Single-page apps.

If it isn't working

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