Python SDK

Track revenue, signups, product usage, and user identity from your Python backend using the official Ripples SDK.

Server-side tracking. Use the Python SDK to send events from your backend — ideal for tracking payments processed server-side, webhooks, or any event that shouldn't go through the browser.

Install

pip install ripples

Add your secret key to your environment:

RIPPLES_SECRET_KEY=priv_your_secret_key

Your secret key can be found in your Ripples dashboard under Settings → API Keys.

Quick start

from ripples import Ripples

ripples = Ripples()

# Track a payment
ripples.revenue(49.99, "user_123")

# Track a signup
ripples.signup("user_123", email="[email protected]")

# Track product usage
ripples.track("created a budget", "user_123", area="budgets")

# Identify / update a user
ripples.identify("user_123", email="[email protected]")

Events are batched in memory and sent automatically when the process exits.

Track revenue

Call revenue() whenever a payment is processed on your server:

ripples.revenue(49.99, "user_123")

Pass extra context as keyword arguments. Any key that isn't a known field becomes a custom property automatically:

ripples.revenue(49.99, "user_123",
    email="[email protected]",
    currency="EUR",
    transaction_id="txn_abc123",
    name="Pro Plan",
    plan="annual",       # custom property
    coupon="WELCOME20",  # custom property
)

Refunds are negative revenue:

ripples.revenue(-29.99, "user_123", transaction_id="txn_abc123")

Parameters

Parameter Type Description
amount required float Revenue amount in your default currency. Use negative values for refunds.
user_id required str Your internal user ID.
**attributes optional Any Additional properties: email, currency, transaction_id, name, plus any custom keys.

Track product usage

Call track() when a user does something meaningful in your product. This powers the Activation dashboard — showing which product areas drive engagement and conversion.

# User did something meaningful
ripples.track("created a budget", "user_123", area="budgets")

# User added their 10th transaction — we consider this their activation moment
ripples.track("added transaction", "user_123",
    area="transactions",
    activated=True,  # marks THIS occurrence as the activation moment
)

How it works. Ripples auto-detects activation moments (first occurrence per user per action), computes adoption rates by product area, and correlates usage patterns with retention and payment.

Parameters

Parameter Type Description
action_name required str What the user did. Be specific: 'created a budget', not 'budgets'.
user_id required str Your internal user ID.
area optional str Product area this action belongs to (e.g. 'budgets', 'reports'). Groups actions in the dashboard.
activated optional bool Set to True on the specific occurrence when activation happens for this user. This does not mark the event type as an activation event — it marks this particular moment as when the user activated. For example, 'sent message' is a regular event, but when a user sends their 10th message you may consider that their activation moment and send that occurrence with activated=True.

Track signups

Call signup() when a new user registers:

ripples.signup("user_123",
    email="[email protected]",
    name="Jane Smith",
    referral="twitter",  # custom property
    plan="free",          # custom property
)

Django example

from ripples import Ripples

def register(request):
    user = User.objects.create_user(...)

    ripples = Ripples()
    ripples.signup(str(user.id),
        email=user.email,
        name=user.get_full_name(),
        ripples_visitor_id=request.COOKIES.get("_rpl_vid"),
    )
    ripples.flush()

    return JsonResponse({"id": user.id})

Flask example

from ripples import Ripples

@app.route("/register", methods=["POST"])
def register():
    user = create_user(...)

    ripples = Ripples()
    ripples.signup(str(user.id),
        email=user.email,
        name=user.name,
        ripples_visitor_id=request.cookies.get("_rpl_vid"),
    )
    ripples.flush()

    return jsonify({"id": user.id})

Tip: pass the visitor ID. Include ripples_visitor_id with the value from the _rpl_vid cookie to link this signup back to the anonymous browsing session and correct traffic source attribution.

Identify users

Call identify() to update user traits at any time — on login, plan change, profile update, etc.:

ripples.identify("user_123",
    email="[email protected]",
    name="Jane Smith",
    avatar_url="https://example.com/avatars/jane.jpg",
    company="Acme Inc",  # custom property
    role="admin",          # custom property
)

Properties

Key Type Description
email optional str User's email address. Shown in the visitor profile and used for Stripe revenue attribution.
name optional str Display name shown in the visitor profile.
avatar_url optional str URL to the user's avatar image. Displayed in the visitor profile. Also accepted as avatar.
[custom] optional str | int | float Any additional traits you want to attach to the user (e.g. plan, company, role).

Error handling

By default, errors during flush are swallowed so your app is never disrupted by a Ripples outage. Use on_error to log them:

import logging

ripples = Ripples(on_error=lambda e: logging.warning(f"Ripples error: {e}"))

You can also catch errors explicitly:

from ripples import RipplesError

try:
    ripples.revenue(49.99, "user_123")
    ripples.flush()
except RipplesError as e:
    # Log or handle gracefully — never block the user flow
    logging.warning(f"Ripples error: {e}")

Configuration

The SDK reads RIPPLES_SECRET_KEY from your environment automatically. You can also pass it explicitly:

ripples = Ripples("priv_explicit_key",
    base_url="https://your-domain.com/api",  # self-hosted
    timeout=10,  # seconds (default: 3)
)

The self-hosted URL can also be set via env:

RIPPLES_URL=https://your-domain.com/api

Configuration options

Option Default Description
base_url https://api.ripples.sh API endpoint. Override for self-hosted deployments.
timeout 3 HTTP read timeout in seconds.
connect_timeout 2 HTTP connection timeout in seconds.
max_queue_size 100 Auto-flush when the queue reaches this size.

Flush manually

Events are batched and sent automatically when the Python process exits (via atexit). For long-running processes, web servers, or CLI scripts, call flush() explicitly:

ripples.flush()

Web frameworks. In Django or Flask, call flush() at the end of each request (or use middleware) to ensure events are delivered promptly. The auto-flush on exit works best for CLI scripts and short-lived processes.

Custom HTTP client

Subclass and override _post() to use httpx, aiohttp, or any other HTTP library:

class MyRipples(Ripples):
    def _post(self, path: str, data: dict) -> None:
        # your custom implementation using httpx, etc.
        pass

Requirements

  • Python 3.9+
  • requests