# Server-side analytics SDKs

> Server-side analytics SDKs for Node.js, Python, PHP, Go and Ruby that wrap the ingest API and batch events. They are not published yet, so read the warning.

The SDKs wrap the ingest API (and the [management API](/docs/api)). They
split lists into batches of 100, convert timestamps to ISO 8601, and return
the per-event results. All are MIT licensed and never log or store the IP
and User-Agent you pass.

| Language | Install | Package |
|---|---|---|
| Node.js (≥ 18, ESM + CJS, TypeScript) | `npm install @privatus/node` | `@privatus/node` |
| Python (≥ 3.9, sync and async) | `pip install privatus` | `privatus` |
| PHP (≥ 8.1) | `composer require privatus/privatus-php` | `privatus/privatus-php` |
| Go (≥ 1.21, standard library only) | `go get github.com/privatus-analytics/privatus-go` | `privatus` |
| Ruby | `gem install privatus` | `Privatus` |

> **Warning:** These SDKs are not published yet (not on npm, PyPI,
> Packagist, the Go module proxy or RubyGems). Until they are, don't
> install packages with these names from public registries, because anyone
> could have published them. Call the ingest API directly instead, as in
> the [examples](/docs/server-side/examples).

## Node.js

```ts
import { Ingest, event } from '@privatus/node'

const ingest = new Ingest(process.env.PRIVATUS_INGEST_KEY!)

const results = await ingest.track([
  event('Purchase', 'https://example.com/checkout', {
    user_agent: req.get('user-agent'),
    ip: req.ip,
    revenue: 49.99,
    currency: 'USD',
    props: { plan: 'pro' },
  }),
])
// [{ index: 0, status: 'accepted', reason: null }]
```

## Python

```python
from privatus import Ingest, event

ingest = Ingest(os.environ["PRIVATUS_INGEST_KEY"])
ingest.track([
    event("Purchase", "https://example.com/checkout",
          user_agent=request.headers.get("User-Agent"),
          revenue=49.99, currency="USD", props={"plan": "pro"}),
])
```

## PHP

```php
use Privatus\Ingest;

$ingest = new Ingest(getenv('PRIVATUS_INGEST_KEY'));
$ingest->track([
    Ingest::event('Purchase', 'https://example.com/checkout',
        props: ['plan' => 'pro'], userAgent: $_SERVER['HTTP_USER_AGENT'] ?? null,
        revenue: 49.99, currency: 'USD'),
]);
```

## Go

```go
ingest := privatus.NewIngest(os.Getenv("PRIVATUS_INGEST_KEY"))
results, err := ingest.Track(r.Context(),
	privatus.CustomEvent("Purchase", "https://example.com/checkout", privatus.EventOptions{
		UserAgent: r.UserAgent(),
		Revenue:   49.99,
		Currency:  "USD",
		Props:     map[string]any{"plan": "pro"},
	}),
)
```

## Ruby

```ruby
require "privatus"

ingest = Privatus::Ingest.new(ENV.fetch("PRIVATUS_INGEST_KEY"))
ingest.track([
  Privatus::Ingest.event("Purchase", "https://example.com/checkout",
                         user_agent: request.user_agent, revenue: 49.99,
                         currency: "USD", props: { plan: "pro" })
])
```

## Mobile apps

SDKs for Swift, Kotlin, Flutter and React Native track screens as
pageviews. Their READMEs cover installation. They use the same public
collection endpoint as the browser tracker, never an ingest key.
