Installation
Install the tracker on any platform, from plain HTML to Next.js and SvelteKit.
There are two ways to install the tracker: a script tag, or the npm package. Both do exactly the same thing. Use the script tag for sites you edit as HTML, and npm for bundled apps.
Script tag
<script src="https://collector.launchpulse.dev/lp.js"></script>
<script>LaunchPulse.init("lp_pub_yourkey");</script>
This sets window.LaunchPulse, and after init() it also sets window.lp as a shorthand.
npm
npm i @basekick-labs/launchpulse
import { LaunchPulse } from "@basekick-labs/launchpulse";
if (typeof window !== "undefined") LaunchPulse.init("lp_pub_yourkey");
The package has zero dependencies, weighs about 1.9 kB gzipped, and is MIT licensed.
SSR-safe: the export is
undefinedon the server. Always guard withtypeof window !== 'undefined', or callinit()inside a client-only lifecycle hook. Every framework example below does this.
About your key
Your public key is lp_pub_ followed by 22 base58 characters. It is designed to ship in client code — embedding it in your HTML or bundle is safe and expected.
There is a separate secret key, lp_sec_ followed by 43 characters, used for server-side ingest. It’s shown once when created and must never appear in browser code.
Where the snippet goes
| Platform | Where | Install |
|---|---|---|
| Plain HTML | <head>, or just before </body> | script |
| WordPress | Theme header before </head>, or a header-scripts plugin | script |
| Ghost | Settings → Code injection → Site Header | script |
| Joomla | Custom HTML module in a header position | script |
| Webflow | Project Settings → Custom Code → Head Code | script |
| Shopify | theme.liquid, before </head> | script |
| Astro | Base layout <head> | script |
| Next.js | Client component in app/layout.tsx | npm |
| React | Root component, in a useEffect | npm |
| Vue | main.ts after createApp, or App.vue onMounted | npm |
| SvelteKit | Root +layout.svelte, in onMount | npm |
| Other | HTML <head>, or npm in a bundled app | script |
Plain HTML
Paste the script tag into the <head> of every page you want tracked. Just before </body> works too.
WordPress
Two options:
- Theme header — Appearance → Theme File Editor →
header.php, paste before</head>. Note that a theme update can overwrite this. - A header/footer scripts plugin — WPCode or similar. This survives theme updates, so it’s the safer choice.
Ghost
Ghost Admin → Settings → Code injection → Site Header. Paste the script tag and save.
Joomla
Add a Custom HTML module assigned to a header position, with the editor in source mode. Alternatively, paste the tag into your template’s index.php inside <head>.
Webflow
Project Settings → Custom Code → Head Code. Paste the tag and republish the site — custom code only takes effect on published sites, not in the designer.
Shopify
Edit your theme’s theme.liquid and paste the tag just before </head>. This covers every page of the storefront.
Astro
Add it to your base layout’s <head>:
---
// src/layouts/Base.astro
---
<head>
<script is:inline src="https://collector.launchpulse.dev/lp.js"></script>
<script is:inline>LaunchPulse.init("lp_pub_yourkey");</script>
</head>
is:inline keeps Astro from processing and bundling the tags.
Next.js (App Router)
Create a client component and mount it in your root layout.
// app/launchpulse.tsx
"use client";
import { useEffect } from "react";
import { LaunchPulse } from "@basekick-labs/launchpulse";
export function LaunchPulseTracker() {
useEffect(() => {
LaunchPulse.init("lp_pub_yourkey");
}, []);
return null;
}
// app/layout.tsx
import { LaunchPulseTracker } from "./launchpulse";
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<body>
<LaunchPulseTracker />
{children}
</body>
</html>
);
}
On the Pages Router, mount the same component in _app.tsx.
React
Call init() once in your root component:
// src/App.tsx
import { useEffect } from "react";
import { LaunchPulse } from "@basekick-labs/launchpulse";
export default function App() {
useEffect(() => {
LaunchPulse.init("lp_pub_yourkey");
}, []);
return <YourApp />;
}
The empty dependency array matters — init() should run once per page load.
Vue
In your entry file, after creating the app:
// src/main.ts
import { createApp } from "vue";
import { LaunchPulse } from "@basekick-labs/launchpulse";
import App from "./App.vue";
createApp(App).mount("#app");
if (typeof window !== "undefined") LaunchPulse.init("lp_pub_yourkey");
Or inside App.vue:
<script setup lang="ts">
import { onMounted } from "vue";
import { LaunchPulse } from "@basekick-labs/launchpulse";
onMounted(() => {
LaunchPulse.init("lp_pub_yourkey");
});
</script>
SvelteKit
Use onMount in the root layout — it only runs in the browser, which keeps SSR safe:
<!-- src/routes/+layout.svelte -->
<script lang="ts">
import { onMount } from "svelte";
import { LaunchPulse } from "@basekick-labs/launchpulse";
onMount(() => {
LaunchPulse.init("lp_pub_yourkey");
});
</script>
<slot />
Other platforms
If your platform lets you edit HTML, put the script tag in the <head>. If it’s a bundled JavaScript app, use the npm package with the typeof window guard.
Self-hosting the collector
The default collector is https://collector.launchpulse.dev, so the snippets generated in the app leave the collector option out. You only need to set it for a self-hosted deployment:
LaunchPulse.init("lp_pub_yourkey", { collector: "https://collector.example.com" });
What you get automatically
$pageview fires on init() and on SPA navigation. The tracker hooks history.pushState and history.replaceState, plus popstate, and deduplicates by path and query string — so an SPA that calls replaceState constantly won’t inflate your pageview count.
$identify is emitted when you call identify(). Call it before your first-value event so the event can be tied to a user.
Verify it
Open your site, then check the debug view in your project. Every event shows up there live. Full walkthrough in Quickstart, step 6.
Remember: while your project is in setup status, nothing is stored. See Going live.