vTilt
Why vTiltHow It WorksFeaturesFAQDocs
Docs / Python
Quick startEvent forwarding
MCP server
Guides
OverviewAuthenticationOAuthAgent skills (prompts)AI intelligenceGoogle Ads
Client setup
CursorClaude DesktopVS CodeCodex
Realtime
Debug ViewRealtime Dashboard
Integration guides
Frontend frameworks
Next.jsNuxt.jsVue.jsReactReact RouterRemixGatsbySvelte / SvelteKitAstroAngularTanStack StartDocusaurus
Backend frameworks
NestJSHonoCloudflare WorkersDjangoFlaskLaravelPhoenixRuby on Rails
Backend languages
PythonPHPRubyElixirGoJava.NET / C#Rust
Stack guides
Vue + PHP
SDK
Browser SDK
InstallScript bundlesEvent trackingAutocaptureIdentify & aliasWeb VitalsSession recordingChat widgetFeature readinessRemote configurationReverse proxyDebug logging
Node SDK
Install & setupCapture, identify & aliasContext & shutdown

Documentation

vTilt
Quick startEvent forwarding

MCP server

Realtime

Debug ViewRealtime Dashboard

Integration guides

PythonPHPRubyElixirGoJava.NET / C#Rust

SDK

DocsIntegration guidesPython

Python

Send vTilt events from any Python code (FastAPI, scripts, jobs) by POSTing to the ingest API. Compatible with the Browser SDK's wire format.

There's no native Python SDK yet, but vTilt's wire format is a plain JSON POST so any Python code can emit events. Use this guide for non-framework Python projects (FastAPI, scripts, scheduled jobs, data pipelines). For Django and Flask, see the dedicated Django and Flask guides.

#1. Configure

# .env
VTILT_TOKEN=YOUR_PROJECT_TOKEN
VTILT_HOST=https://www.vtilt.com
text

#2. Capture helper

A 20-line client built on urllib. No third-party dependencies. Add requests or httpx if you want connection pooling.

# vtilt.py
import json
import os
from urllib.request import Request, urlopen

VTILT_TOKEN = os.environ['VTILT_TOKEN']
VTILT_HOST = os.environ.get('VTILT_HOST', 'https://www.vtilt.com')


def capture(distinct_id: str, event: str, properties: dict | None = None) -> None:
    payload = json.dumps({
        'api_key': VTILT_TOKEN,
        'event': event,
        'distinct_id': distinct_id,
        'properties': properties or {},
    }).encode('utf-8')

    req = Request(
        f'{VTILT_HOST}/api/e',
        data=payload,
        headers={'Content-Type': 'application/json'},
        method='POST',
    )
    try:
        urlopen(req, timeout=2).read()
    except Exception:
        pass  # never block on analytics


def identify(distinct_id: str, properties: dict) -> None:
    capture(distinct_id, '$identify', {'$set': properties})
python

#3. Capture events

from vtilt import capture, identify

identify('user_42', {'email': 'alice@example.com', 'plan': 'pro'})

capture('purchase_completed', distinct_id='user_42', properties={
    'amount': 99.99,
    'currency': 'USD',
})
python

#4. FastAPI integration

from fastapi import FastAPI, BackgroundTasks
from vtilt import capture

app = FastAPI()

@app.post('/checkout')
async def checkout(req: dict, bg: BackgroundTasks):
    bg.add_task(capture, req['user_id'], 'purchase_completed', {'amount': req['amount']})
    return {'ok': True}
python

Tip

Tip: Run captures in BackgroundTasks (FastAPI), Celery/RQ workers, or a concurrent.futures.ThreadPoolExecutor so analytics never blocks the user-facing response.

#Next steps

  • Django integration guide — Django-specific helpers + base template.
  • Flask integration guide — Flask-specific helpers + Jinja base template.
  • Identify & alias — full identification model.
  • Event forwarding — fan events out to GA4, Meta CAPI, PostHog.
PreviousRuby on RailsIntegration guidesNextPHPIntegration guides

On this page

  • 1. Configure
  • 2. Capture helper
  • 3. Capture events
  • 4. FastAPI integration
  • Next steps