> ## 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.

# Vanilla JavaScript, Vue, Svelte & More

> Use Grain Analytics with any JavaScript framework or no framework at all

<Note>
  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](/quickstart/react) or [Next.js Quick Start](/quickstart/nextjs) instead.
</Note>

## Option 1: Script Tag (Recommended)

Add the Grain Tag script to your HTML:

```html theme={null}
<script src="https://tag.grainql.com/v4/your-tenant-id.js"></script>
```

Replace `your-tenant-id` with your tenant identifier from your [dashboard](https://grainql.com/dashboard).

Then get the SDK instance in your JavaScript:

```javascript theme={null}
const grain = GrainTag.getInstance();
```

## Option 2: npm Package

Install via your package manager:

```bash npm theme={null}
npm install @grainql/tag
```

```bash yarn theme={null}
yarn add @grainql/tag
```

```bash pnpm theme={null}
pnpm add @grainql/tag
```

Then import and initialize:

```javascript theme={null}
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:

```javascript theme={null}
// 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:

```javascript theme={null}
// 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
```

## Consent Management

Grain is cookieless by default with daily rotating IDs. When you need explicit consent handling:

```javascript theme={null}
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:

```html theme={null}
<!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`):

```html theme={null}
<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**:

```html theme={null}
<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`):

```typescript theme={null}
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`):

```svelte theme={null}
<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**:

```svelte theme={null}
<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:

```typescript theme={null}
// 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?

<CardGroup cols={2}>
  <Card title="Core API Reference" icon="book" href="/api-reference/core-methods">
    See all available methods and options
  </Card>

  <Card title="User Identification" icon="user" href="/core/user-identification">
    Learn about tracking users across sessions
  </Card>

  <Card title="Trackers" icon="crosshairs" href="/features/trackers">
    Track element clicks without writing code
  </Card>

  <Card title="Event Best Practices" icon="chart-line" href="/core/event-tracking">
    Learn what to track and how to structure events
  </Card>
</CardGroup>

<Note>
  **Need remote configuration or feature flags?** See [@grainql/analytics-web](/react/overview) for remote config support, React hooks, and more.
</Note>
