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

# Core Methods

> Event tracking and user management methods for both Grain SDKs

## Grain Tag Methods

<Info>
  **Primary SDK for browser analytics.** Import from `@grainql/tag`.
</Info>

```typescript theme={null}
import { init, track, identify, getInstance, isInitialized, destroy } from '@grainql/tag';
```

***

### init()

Creates and returns the singleton `GrainTagInstance`. In non-browser environments (Node, SSR), returns a safe no-op stub.

```typescript theme={null}
function init(config?: Partial<GrainTagConfig>): GrainTagInstance
```

**Parameters:**

* `config` — Configuration object. `tenantId` is the only required field.

**Returns:** `GrainTagInstance`

**Example:**

```typescript theme={null}
const grain = init({ tenantId: 'your-tenant-id' });
```

If called more than once, returns the existing instance and logs a warning. Use `destroy()` first to re-initialize with new config.

***

### track()

Track a custom event. If called before `init()`, the event is queued and replayed automatically once the SDK initializes.

```typescript theme={null}
function track(eventName: string, properties?: Record<string, unknown>): void
```

**Parameters:**

* `eventName` — Name of the event
* `properties` — Optional key-value pairs

**Example:**

```typescript theme={null}
track('button_clicked', { button: 'signup', page: '/pricing' });
```

***

### identify()

Set user identity. If called before `init()`, the call is queued and replayed after initialization.

```typescript theme={null}
function identify(userId: string): void
```

**Parameters:**

* `userId` — User identifier

**Example:**

```typescript theme={null}
identify('user-123');
```

***

### getInstance()

Get the existing SDK instance, or `null` if not yet initialized.

```typescript theme={null}
function getInstance(): GrainTagInstance | null
```

**Example:**

```typescript theme={null}
const grain = getInstance();
if (grain) {
  grain.track('custom_event');
}
```

***

### isInitialized()

Check whether the SDK has been initialized.

```typescript theme={null}
function isInitialized(): boolean
```

**Example:**

```typescript theme={null}
if (!isInitialized()) {
  init({ tenantId: 'your-tenant-id' });
}
```

***

### destroy()

Tear down the SDK instance and clear the singleton. After calling this, you can call `init()` again with new config.

```typescript theme={null}
function destroy(): void
```

**Example:**

```typescript theme={null}
destroy();
```

***

### Instance Methods

Once you have a `GrainTagInstance` (from `init()` or `getInstance()`), these methods are available:

#### grain.track()

Same as the top-level `track()`, but called on the instance directly.

```typescript theme={null}
grain.track(eventName: string, properties?: Record<string, unknown>): void
```

#### grain.identify()

Same as the top-level `identify()`, but called on the instance directly.

```typescript theme={null}
grain.identify(userId: string): void
```

#### grain.consent.grant()

Grant consent. Upgrades from cookieless to permanent identity tracking.

```typescript theme={null}
grain.consent.grant(categories?: string[]): void
```

**Parameters:**

* `categories` — Consent categories to grant. Defaults to `['necessary', 'analytics', 'functional']`.

**Example:**

```typescript theme={null}
// Grant all default categories
grain.consent.grant();

// Grant specific categories
grain.consent.grant(['necessary', 'analytics']);
```

#### grain.consent.revoke()

Revoke consent. Downgrades back to cookieless identity mode.

```typescript theme={null}
grain.consent.revoke(categories?: string[]): void
```

**Parameters:**

* `categories` — Categories to revoke. If omitted, revokes all.

**Example:**

```typescript theme={null}
grain.consent.revoke();
```

#### grain.consent.status()

Get the current consent state.

```typescript theme={null}
grain.consent.status(): ConsentState | null
```

**Returns:** `ConsentState` object or `null` if no consent decision has been made.

```typescript theme={null}
interface ConsentState {
  granted: boolean;
  categories: string[];
  timestamp: number;
  version: string;
}
```

**Example:**

```typescript theme={null}
const status = grain.consent.status();
if (status?.granted) {
  console.log('Consent granted for:', status.categories);
}
```

#### grain.flush()

Force-send all pending events immediately.

```typescript theme={null}
grain.flush(): Promise<void>
```

**Example:**

```typescript theme={null}
await grain.flush();
```

#### grain.destroy()

Tear down the instance. Same as the top-level `destroy()`.

```typescript theme={null}
grain.destroy(): void
```

#### grain.isReady()

Returns `true` if the SDK is fully initialized in a browser environment.

```typescript theme={null}
grain.isReady(): boolean
```

***

## Analytics Web Methods

<Info>
  **For remote config, React hooks, and server-side tracking.** Import from `@grainql/analytics-web`.
</Info>

```typescript theme={null}
import { createGrainAnalytics } from '@grainql/analytics-web';
```

***

### createGrainAnalytics()

Creates a new Grain client instance.

```typescript theme={null}
const grain = createGrainAnalytics(config: GrainConfig): GrainAnalytics
```

**Parameters:**

* `config` — Configuration object (see [Types](/api-reference/types))

**Returns:** GrainAnalytics client instance

**Example:**

```typescript theme={null}
const grain = createGrainAnalytics({
  tenantId: 'your-tenant-id',
  userId: 'user_123'
});
```

***

### track()

Track an event. Two signatures available:

#### track(eventName, properties?, options?)

```typescript theme={null}
grain.track(
  eventName: string,
  properties?: Record<string, unknown>,
  options?: SendEventOptions
): Promise<void>
```

**Parameters:**

* `eventName` — Name of the event
* `properties` — Optional event properties
* `options.flush` — Force immediate send (default: false)

**Example:**

```typescript theme={null}
grain.track('button_clicked', {
  button: 'signup',
  page: '/home'
});

// With flush
await grain.track('purchase', { total: 99.99 }, { flush: true });
```

#### track(event, options?)

```typescript theme={null}
grain.track(
  event: GrainEvent,
  options?: SendEventOptions
): Promise<void>
```

**Parameters:**

* `event` — Complete event object
* `options.flush` — Force immediate send

**Example:**

```typescript theme={null}
grain.track({
  eventName: 'purchase',
  userId: 'user_123',
  properties: { total: 99.99 },
  timestamp: new Date()
});
```

***

### flush()

Manually flush all queued events.

```typescript theme={null}
await grain.flush(): Promise<void>
```

**Returns:** Promise that resolves when events are sent

**Example:**

```typescript theme={null}
await grain.flush();
console.log('All events sent');
```

**When to use:**

* Before page navigation
* Critical events
* Serverless functions
* Before app closes

***

### setUserId()

Set global user ID for all subsequent events.

```typescript theme={null}
grain.setUserId(userId: string | null): void
```

**Parameters:**

* `userId` — User identifier, or `null` to clear

**Example:**

```typescript theme={null}
// Set user ID
grain.setUserId('user_123');

// Clear on logout
grain.setUserId(null);
```

***

### identify()

Alias for `setUserId()`. Sets user ID for subsequent events.

```typescript theme={null}
grain.identify(userId: string | null): void
```

**Example:**

```typescript theme={null}
grain.identify('user_123');
```

***

### getUserId()

Get current user ID.

```typescript theme={null}
grain.getUserId(): string | null
```

**Returns:** Current user ID or `null` if not set

**Example:**

```typescript theme={null}
const userId = grain.getUserId();
if (userId) {
  console.log(`Tracking as: ${userId}`);
}
```

***

### setProperty()

Set user properties for analytics and personalization.

```typescript theme={null}
await grain.setProperty(
  properties: Record<string, unknown>,
  options?: SetPropertyOptions
): Promise<void>
```

**Parameters:**

* `properties` — Up to 4 key-value pairs (values converted to strings)
* `options.userId` — Optional user ID override

**Returns:** Promise that resolves when properties are set

**Example:**

```typescript theme={null}
// Set for current user
await grain.setProperty({
  plan: 'premium',
  location: 'US',
  signup_date: '2024-01-15'
});

// Set for specific user
await grain.setProperty({
  status: 'active'
}, { userId: 'user_456' });
```

**Limits:**

* Maximum 4 properties per request
* All values converted to strings
* Subject to rate limiting

***

### destroy()

Clean up resources and send remaining events.

```typescript theme={null}
grain.destroy(): void
```

**Example:**

```typescript theme={null}
// On app unmount
grain.destroy();
```

**What it does:**

* Flushes queued events
* Removes event listeners
* Cleans up timers
* Stops auto-refresh

***

## Next Steps

<CardGroup cols={2}>
  <Card title="Config Methods" icon="sliders" href="/api-reference/config-methods">
    Remote configuration methods
  </Card>

  <Card title="Template Methods" icon="sparkles" href="/api-reference/template-methods">
    Pre-built event methods
  </Card>

  <Card title="Types" icon="code-simple" href="/api-reference/types">
    TypeScript type definitions
  </Card>
</CardGroup>
