Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.grainql.com/llms.txt

Use this file to discover all available pages before exploring further.

This guide works with Vue, Svelte, Angular, or plain JavaScript — either via script tag or npm. Using React or Next.js? Try the React Quick Start or Next.js Quick Start instead.
Add the Grain Tag script to your HTML:
<script src="https://tag.grainql.com/v4/your-tenant-id.js"></script>
Replace your-tenant-id with your tenant identifier from your dashboard. Then get the SDK instance in your JavaScript:
const grain = GrainTag.getInstance();

Option 2: npm Package

Install via your package manager:
npm
npm install @grainql/tag
yarn
yarn add @grainql/tag
pnpm
pnpm add @grainql/tag
Then import and initialize:
import { init, track, identify, getInstance } from '@grainql/tag';

init({ tenantId: 'your-tenant-id' });
With the npm package, you can use the top-level exports (track, identify) directly, or get the instance with getInstance().

Automatic Tracking

Grain Tag automatically tracks the following with zero configuration:
  • Page views — including SPA navigation via the History API
  • Heatmap clicks — click positions with element identification
  • Scroll depth — how far users scroll on each page
  • DOM snapshots — visual page captures for heatmap overlays
  • Sessions — session start/end with duration
  • Device, browser, and OS — automatically detected
  • UTM parameters and referrer — captured on first visit
No manual page_viewed calls are needed. Grain Tag hooks into pushState and replaceState automatically.

Track Custom Events

Call track() with an event name and optional properties:
// Script tag approach
const grain = GrainTag.getInstance();
grain.track('button_clicked', {
  button_name: 'signup',
  location: 'hero'
});

// npm approach
import { track } from '@grainql/tag';
track('button_clicked', {
  button_name: 'signup',
  location: 'hero'
});
Events are automatically batched and sent. You don’t need to manually flush.

Identify Users

Associate events with a specific user:
// Script tag approach
const grain = GrainTag.getInstance();
grain.identify('user_123');

// npm approach
import { identify } from '@grainql/tag';
identify('user_123');

// All subsequent events include this user ID
Grain is cookieless by default with daily rotating IDs. When you need explicit consent handling:
const grain = GrainTag.getInstance();

// Grant consent (enables persistent tracking)
grain.consent.grant();

// Revoke consent
grain.consent.revoke();

// Check consent status
const status = grain.consent.status();

Complete Example

Here’s a small app that puts it all together:
<!DOCTYPE html>
<html lang="en">
<head>
  <script src="https://tag.grainql.com/v4/your-tenant-id.js"></script>
</head>
<body>
  <div id="hero">
    <h1>Welcome!</h1>
  </div>
  <button id="signup-btn">Get Started</button>

  <script>
    const grain = GrainTag.getInstance();

    // Track button clicks
    document.querySelector('#signup-btn').addEventListener('click', () => {
      grain.track('signup_clicked', { location: 'hero' });
    });

    // Identify user after login
    async function handleLogin(email, password) {
      const user = await loginUser(email, password);
      grain.identify(user.id);
    }
  </script>
</body>
</html>

Vue.js Example

Using Grain Tag in a Vue component: Script tag approach (add <script src="https://tag.grainql.com/v4/your-tenant-id.js"></script> to your index.html):
<template>
  <div>
    <h1>{{ title }}</h1>
    <button @click="handleClick">Get Started</button>
  </div>
</template>

<script setup>
import { ref, onMounted } from 'vue';

const title = ref('Welcome!');

const handleClick = () => {
  const grain = GrainTag.getInstance();
  grain.track('button_clicked', { location: 'hero' });
};
</script>
npm approach:
<template>
  <div>
    <h1>{{ title }}</h1>
    <button @click="handleClick">Get Started</button>
  </div>
</template>

<script setup>
import { ref } from 'vue';
import { track } from '@grainql/tag';

const title = ref('Welcome!');

const handleClick = () => {
  track('button_clicked', { location: 'hero' });
};
</script>
Initialize Grain once in your app entry point (main.ts):
import { createApp } from 'vue';
import { init } from '@grainql/tag';
import App from './App.vue';

init({ tenantId: 'your-tenant-id' });

createApp(App).mount('#app');
Page views are tracked automatically — Grain Tag hooks into Vue Router’s History API navigation.

Svelte Example

Using Grain Tag in a Svelte component: Script tag approach (add <script src="https://tag.grainql.com/v4/your-tenant-id.js"></script> to your app.html):
<script>
  function handleClick() {
    const grain = GrainTag.getInstance();
    grain.track('button_clicked', { location: 'hero' });
  }
</script>

<div>
  <h1>Welcome!</h1>
  <button on:click={handleClick}>Get Started</button>
</div>
npm approach:
<script>
  import { track } from '@grainql/tag';

  function handleClick() {
    track('button_clicked', { location: 'hero' });
  }
</script>

<div>
  <h1>Welcome!</h1>
  <button on:click={handleClick}>Get Started</button>
</div>
Initialize Grain once in your app entry point:
// src/main.ts
import { init } from '@grainql/tag';
import App from './App.svelte';

init({ tenantId: 'your-tenant-id' });

const app = new App({ target: document.getElementById('app')! });
export default app;
Page views are tracked automatically — Grain Tag hooks into SvelteKit’s History API navigation.

What’s Next?

Core API Reference

See all available methods and options

User Identification

Learn about tracking users across sessions

Trackers

Track element clicks without writing code

Event Best Practices

Learn what to track and how to structure events
Need remote configuration or feature flags? See @grainql/analytics-web for remote config support, React hooks, and more.