# Ingest Data

Send product events and identity updates to Altertable with SDKs or direct HTTP requests. The same payload model writes to the built-in `product_analytics` catalog, so client, server, mobile, and batch sources can be analyzed together.

## Goal

Choose an SDK, connect it with a Product Analytics API key, and send events and identity updates to the built-in `product_analytics` catalog.

## Prerequisites

- Enable [Product Analytics](/docs/product-analytics.md) for the target environment.
- Copy a Product Analytics [API key](/docs/product-analytics/ingest-data/authentication.md).
- Choose a client-side or server-side SDK based on where your application sends events.

## Steps

### 1. Install an SDK

Product Analytics SDKs follow the same mental model across languages:

| Language                | Install                                                                                                                                                  | Repository                                                   |
| ----------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------ |
| TypeScript / JavaScript | `npm install @altertable/altertable-js`                                                                                                                  | [GitHub](https://github.com/altertable-ai/altertable-js/)    |
| React                   | `npm install @altertable/altertable-js @altertable/altertable-react`                                                                                     | [GitHub](https://github.com/altertable-ai/altertable-js/)    |
| Python                  | `pip install altertable` or `poetry add altertable`                                                                                                      | [GitHub](https://github.com/altertable-ai/altertable-python) |
| Ruby                    | `gem install altertable`                                                                                                                                 | [GitHub](https://github.com/altertable-ai/altertable-ruby)   |
| Swift                   | Swift Package Manager                                                                                                                                    | [GitHub](https://github.com/altertable-ai/altertable-swift)  |
| Kotlin / Android        | JVM: `implementation("ai.altertable.sdk:altertable-kotlin:0.1.0")`; Android apps also add `implementation("ai.altertable.sdk:altertable-android:0.1.0")` | [GitHub](https://github.com/altertable-ai/altertable-kotlin) |

### 2. Initialize the client and send data

Use these examples as the starting point for your application code:

### TypeScript

```typescript
import { altertable } from '@altertable/altertable-js';

// Initialize with your API key
altertable.init('{{API_KEY}}', {
  environment: '{{ENVIRONMENT_SLUG}}',
});

// Track a user event
altertable.track('checkout_completed', {
  revenue: 49.99,
  plan: 'pro',
  currency: 'USD',
});

// Identify a user
altertable.identify('user_abc123', {
  email: 'alice@acme.com',
  plan: 'pro',
});
```

### React

```tsx
import { altertable } from '@altertable/altertable-js';
import {
  AltertableProvider,
  useAltertable,
} from '@altertable/altertable-react';

// Initialize the core SDK
altertable.init('{{API_KEY}}', {
  environment: '{{ENVIRONMENT_SLUG}}',
});

function App() {
  return (
    <AltertableProvider client={altertable}>
      <CheckoutPage />
    </AltertableProvider>
  );
}

function CheckoutPage() {
  const { track, identify } = useAltertable();

  function handleCheckout() {
    track('checkout_completed', {
      revenue: 49.99,
      plan: 'pro',
      currency: 'USD',
    });
  }

  function handleLogin(userId) {
    identify(userId, {
      email: 'alice@acme.com',
      plan: 'pro',
    });
  }

  return (
    <div>
      <button onClick={handleCheckout}>Complete Checkout</button>
      <button onClick={() => handleLogin('user_abc123')}>Login</button>
    </div>
  );
}
```

### Python

```python
from altertable import Altertable

client = Altertable("{{API_KEY}}")

# Track a user event
client.track(
    event="checkout_completed",
    distinct_id="user_abc123",
    options={
        "properties": {
            "revenue": 49.99,
            "plan": "pro",
            "currency": "USD",
        }
    }
)

# Identify a user
client.identify(
    distinct_id="user_abc123",
    options={
        "traits": {
            "email": "alice@acme.com",
            "plan": "pro",
        }
    }
)
```

### Ruby

```ruby
require 'altertable'

Altertable.init('{{API_KEY}}', {
  environment: '{{ENVIRONMENT_SLUG}}'
})

# Track a user event
Altertable.track('checkout_completed', 'user_abc123', properties: {
  revenue: 49.99,
  plan: 'pro',
  currency: 'USD'
})

# Identify a user
Altertable.identify('user_abc123', traits: {
  email: 'alice@acme.com',
  plan: 'pro'
})
```

### Swift

```swift
import Altertable

let client = Altertable(apiKey: "{{API_KEY}}")

// Track a user event
client.track(
    event: "checkout_completed",
    properties: [
        "revenue": 49.99,
        "plan": "pro",
        "currency": "USD"
    ]
)

// Identify a user
client.identify(
    userId: "user_abc123",
    traits: [
        "email": "alice@acme.com",
        "plan": "pro"
    ]
)
```

### Kotlin

```kotlin
import ai.altertable.sdk.Altertable

// Initialize with your API key
Altertable.setup {
    apiKey = "{{API_KEY}}"
    environment = "{{ENVIRONMENT_SLUG}}"
}

// Track a user event
Altertable.shared?.track(
    event = "checkout_completed",
    properties = mapOf(
        "revenue" to 49.99,
        "plan" to "pro",
        "currency" to "USD"
    )
)

// Identify a user
Altertable.shared?.identify(
    userId = "user_abc123",
    traits = mapOf(
        "email" to "alice@acme.com",
        "plan" to "pro"
    )
)
```

After initialization:

1. Track events with event properties.
2. Identify users and attach traits.
3. Optionally alias related identities.

### 3. Choose client-side or server-side behavior

SDKs fall into two categories with different capabilities:

| Capability                        | Client-side | Server-side                                                                                     |
| --------------------------------- | ----------- | ----------------------------------------------------------------------------------------------- |
| Event tracking                    | Yes         | Yes                                                                                             |
| User identification               | Yes         | Yes                                                                                             |
| Aliasing                          | Yes         | Yes                                                                                             |
| Automatic page/screen tracking    | Yes         | No                                                                                              |
| Session and device ID management  | Automatic   | You pass [`distinct_id`](/docs/product-analytics/ingest-data/track.md#distinct-id) on each call |
| Tracking consent                  | Built-in    | Manage externally                                                                               |
| Event queuing and offline support | Yes         | No                                                                                              |

### 4. Configure page, screen, and consent helpers

Client-side SDKs can automatically capture page views or screen views:

### TypeScript

```typescript
// Disable auto-capture if you need manual control
altertable.init('{{API_KEY}}', { autoCapture: false });

// Then track page views manually
altertable.page('https://example.com/products');
```

### Swift

```swift
Text("Welcome")
    .screenView(name: "Home")
```

### Kotlin

```kotlin
Column(modifier = Modifier.screenView(name = "Home")) {
    // Screen content
}
```

They also include built-in consent management for privacy compliance:

### TypeScript

```typescript
// JavaScript — initialize with consent pending
altertable.init('{{API_KEY}}', { trackingConsent: 'pending' });

// Later, when the user grants consent
altertable.configure({ trackingConsent: 'granted' });
```

### Swift

```swift
// Swift — initialize with consent pending
let config = AltertableConfig(trackingConsent: .pending)
let client = Altertable(apiKey: "{{API_KEY}}", config: config)

// Later, when the user grants consent
client.configure { config in
    config.trackingConsent = .granted
}
```

### Kotlin

```kotlin
// Kotlin — initialize with consent pending
Altertable.setup {
    apiKey = "{{API_KEY}}"
    tracking { consent = TrackingConsent.PENDING }
}

// Later, when the user grants consent
Altertable.shared?.configure {
    tracking { consent = TrackingConsent.GRANTED }
}
```

## Verification

Send one event from your application, then query the raw events table:

```sql
SELECT *
FROM product_analytics.main.events
ORDER BY timestamp DESC
LIMIT 10;
```

Confirm that the event name, distinct ID, timestamp, and properties match the payload your application sent.

## Troubleshooting

- **No events appear:** confirm that Product Analytics is enabled in the same environment as the API key.
- **Requests are rejected:** check the [authentication methods](/docs/product-analytics/ingest-data/authentication.md) and replace an incorrect or expired API key.
- **Users remain anonymous:** call `identify` when a stable user ID becomes available, and pass `distinct_id` explicitly from server-side SDKs.
- **Automatic page or screen events are missing:** use a client-side SDK and enable its page or screen helper.

**Continue in Altertable:** [Open Altertable](/app)

## Next steps

- [Authentication](/docs/product-analytics/ingest-data/authentication.md): Authenticate Product Analytics SDKs and API requests with environment-specific API keys for staging and production data.
- [Track](/docs/product-analytics/ingest-data/track.md): Track product events from SDKs or API clients and make behavioral data queryable in your Altertable lakehouse.
- [Identify](/docs/product-analytics/ingest-data/identify.md): Identify users in Altertable Product Analytics so events connect to stable profiles, traits, and business context.
- [Alias](/docs/product-analytics/ingest-data/alias.md): Alias product analytics identifiers in Altertable to merge user profiles when identity systems or user IDs change.