# Python

URL: https://pieowl.com/docs/sdks/python





Pieowl doesn't ship a Python SDK. You send events from Python with a plain HTTP request to the [Track API](/docs/api/track). The example below uses only the standard library, so there is nothing to install.

<Callout>
  Looking for a step-by-step tutorial? Read the [Python analytics guide](/guides/python-analytics).
</Callout>

Before you start [#before-you-start]

You need a client ID and a client secret. Find them in the dashboard under **Settings → Developers → Keys**. Server requests must include the secret, so keep it on your server and load it from an environment variable.

Send an event [#send-an-event]

Every request is a `POST` to `https://api.pieowl.com/track` with a JSON body of `{ "type": ..., "payload": ... }`.

```python title="pieowl.py"
import json
import os
import urllib.request

PIEOWL_URL = "https://api.pieowl.com/track"


def pieowl_send(event_type, payload, client_ip=None, user_agent=None):
    headers = {
        "Content-Type": "application/json",
        "pieowl-client-id": os.environ["PIEOWL_CLIENT_ID"],
        "pieowl-client-secret": os.environ["PIEOWL_CLIENT_SECRET"],
    }
    # Optional: forward the visitor's IP and user agent for location and device data
    if client_ip:
        headers["pieowl-client-ip"] = client_ip
    if user_agent:
        headers["user-agent"] = user_agent

    body = json.dumps({"type": event_type, "payload": payload}).encode()
    request = urllib.request.Request(PIEOWL_URL, data=body, headers=headers, method="POST")
    with urllib.request.urlopen(request, timeout=5) as response:
        return response.status
```

Usage [#usage]

Tracking events [#tracking-events]

```python
pieowl_send("track", {
    "name": "signup",
    "profileId": "user_123",  # optional
    "properties": {"plan": "pro"},
})
```

Identifying users [#identifying-users]

```python
pieowl_send("identify", {
    "profileId": "user_123",  # required
    "firstName": "Joe",
    "lastName": "Doe",
    "email": "joe@doe.com",
    "properties": {"tier": "premium"},
})
```

Incrementing and decrementing properties [#incrementing-and-decrementing-properties]

`value` is optional and defaults to 1.

```python
pieowl_send("increment", {"profileId": "user_123", "property": "visits", "value": 1})
pieowl_send("decrement", {"profileId": "user_123", "property": "credits", "value": 1})
```

Tracking revenue [#tracking-revenue]

A purchase is a `revenue` event with these properties:

* `__amount`: in normal units, like `49.99`, not cents.
* `__currency`: an ISO 4217 code, like `EUR`. Optional, your site currency by default.
* `__orderId`: your order number. The same order sent twice counts once.
* `__deviceId`: the visitor's device ID, from `pieowl.getDeviceId()` in the browser. The purchase is credited to their visit.

For a refund, send the same event with `__refund` set to true. Leave out `__amount` to refund the whole order. See [Revenue attribution](/docs/revenue-attribution).

```python
pieowl_send("track", {
    "name": "revenue",
    "properties": {
        "__amount": 49.99,
        "__currency": "EUR",
        "__orderId": "A-1001",
        "__deviceId": device_id,
    },
})

# Refund the whole order
pieowl_send("track", {
    "name": "revenue",
    "properties": {"__orderId": "A-1001", "__refund": True},
})
```

Good to know [#good-to-know]

* **Errors:** `urlopen` raises `urllib.error.HTTPError` when Pieowl rejects a request, for example a bad client secret or an invalid payload. Catch it so analytics never breaks a user request.
* **Don't block requests:** In a web app, send events from a background thread or task queue.
* **More event types:** Groups and the full request schema are in the [Track API reference](/docs/api/track).
