Python Quickstart
Get Running with the Convert Python SDK in 5 Minutes
THIS ARTICLE WILL HELP YOU:
- Get an Overview
- Install the Convert Python SDK
- Know the Requirements
- Initialize with Direct Configuration
- Some Key Points
- Create a Visitor Context
- Run an Experience
- Server-Side Rendering Pattern
- Track Conversions
- Flush and Close
- Complete Direct Configuration Example
- Remote Initialization
- Context Manager Pattern
- Backend and Front-End Implementation Considerations
- QA Checklist
- Troubleshoot
- Conclusion
Overview
The Convert Python SDK lets you run Convert Full Stack experiments and feature flags directly from Python applications.
It is designed for backend experimentation where your Python application decides which experience, feature, API response, pricing logic, or business workflow a visitor should receive before a response is returned.
Unlike browser SDKs, all visitor evaluation happens locally after the configuration has been loaded.
This Quickstart uses Direct Configuration, which requires no SDK Key and performs no network requests, making it ideal for:
- local development
- automated tests
- CI pipelines
- offline tooling
- development environments
For production deployments, the SDK can instead download live configuration from the Convert CDN using your SDK Key.
Convert Full Stack projects allow experimentation across backend and frontend systems, enabling optimization beyond browser-based experiences.
1. Install the Python SDK
Install the SDK using pip:
pip install convert-python-sdk
Python 3.9 or newer is required.
The SDK installs httpx automatically as its only runtime dependency.
httpx is only used when the SDK is initialized with an SDK Key to download remote configuration.
Direct configuration mode performs no HTTP requests.
Alternative installation methods such as Poetry and uv are also supported.
Requirements
| Requirement | Version |
|---|---|
| Python | 3.9+ |
| Runtime dependency | httpx |
| Network required | Only when using sdk_key |
2. Initialize with Direct Configuration
Direct Configuration allows the SDK to run completely offline.
Instead of downloading configuration from Convert, you provide it directly as a Python dictionary.
This makes the SDK:
- deterministic
- immediately ready
- ideal for tests
- ideal for local development
Example:
from convert_sdk import Core, SDKConfig
config_data = {
"account_id": "100123",
"project": {"id": "200456"},
"experiences": [
{
"id": "e1",
"key": "checkout-experiment",
"variations": [
{
"id": "v1",
"key": "control",
"traffic_allocation": 50.0
},
{
"id": "v2",
"key": "treatment",
"traffic_allocation": 50.0
}
]
}
],
"goals": [
{
"id": "g1",
"key": "purchase_completed"
}
]
}
core = Core(
SDKConfig(data=config_data)
).initialize()
assert core.is_ready
Unlike the mobile SDKs, initialization is fully synchronous.
initialize() blocks until the SDK is ready.
Once initialization completes successfully:
core.is_ready
returns:
True
There is:
- no callback
- no Promise
- no async/await
- no background readiness event
Key Points
Direct Configuration makes no network requests
Providing:
SDKConfig(data=config_data)
loads configuration directly from memory.
No HTTP request is performed.
This makes Direct Configuration safe for:
- unit tests
- integration tests
- CI
- offline environments
- local development
initialize() is synchronous
Initialization blocks until configuration is loaded.
Unlike the Android or iOS SDKs, there is no asynchronous readiness callback.
core = Core(
SDKConfig(data=config_data)
).initialize()
When this returns successfully, the SDK is ready for evaluation.
3. Create a Visitor Context
After the SDK is initialized, create a visitor context.
context = core.create_context(
"visitor-001",
visitor_attributes={
"country": "US",
"plan": "pro"
}
)
A visitor context combines:
- visitor identity
- visitor attributes
- current configuration snapshot
Every evaluation happens against this context.
The SDK does not cache contexts.
Reuse the returned context while processing the same visitor.
Visitor Attributes
Visitor attributes allow experiences to target visitors based on custom information.
Example:
visitor_attributes={
"country": "US",
"plan": "pro"
}
The SDK defensively copies the attribute dictionary.
Any changes made to the original dictionary after calling create_context() do not affect the visitor context.
Stable Visitor IDs
Use a stable visitor identifier whenever possible.
For authenticated users, this is typically your internal user ID.
For anonymous users, use a persistent identifier such as a first-party cookie or another stable anonymous identifier.
Stable visitor identifiers help maintain consistent experiment assignment while the configuration remains unchanged.
4. Running an Experience
Evaluate an experiment using its experience key.
result = context.run_experience(
"checkout-experiment"
)
If the visitor qualifies, the SDK returns an ExperienceResult.
print(result.experience_key)
print(result.variation_key)
print(result.variation_id)
Example output:
checkout-experiment
control
v1
Handling Visitors That Do Not Qualify
A visitor that does not qualify simply returns:
None
Example:
result = context.run_experience(
"checkout-experiment"
)
if result is not None:
render_variation(result.variation_key)
else:
render_default()
None is an expected result.
It is not an exception.
The SDK never raises an exception simply because a visitor did not qualify.
Server-Side Rendering Pattern
One common implementation is deciding the experience before rendering HTML.
Example:
result = context.run_experience(
"checkout-experiment"
)
if result is None:
return render_template(
"checkout_default.html"
)
if result.variation_key == "treatment":
return render_template(
"checkout_new.html"
)
return render_template(
"checkout_default.html"
)
This allows the visitor to receive the correct experience immediately, avoiding browser-side flicker.
Server-side experimentation is particularly useful for:
- Flask
- Django
- FastAPI
- Starlette
- custom WSGI/ASGI applications
5. Tracking Conversions
Track a conversion synchronously.
result = context.track_conversion(
"purchase_completed",
revenue=49.99
)
Inspect the result:
print(result.tracked)
print(result.status)
Example:
True
ConversionStatus.QUEUED
Unlike browser SDKs, tracking a conversion does not immediately perform a network request.
Instead, the SDK appends the event to an in-process queue.
Duplicate Conversions
Conversions are automatically deduplicated by:
- visitor ID
- goal ID
Example:
again = context.track_conversion(
"purchase_completed"
)
print(again.tracked)
print(again.reason)
Output:
False
deduplicated
This prevents accidental duplicate goal tracking.
Repeated Revenue Events
If you intentionally want to record another transaction:
context.track_conversion(
"purchase_completed",
revenue=10.0,
force_multiple=True
)
The conversion remains deduplicated while the additional revenue transaction is recorded.
6. Flush and Close
Unlike some SDKs that automatically send tracking events in the background, the Python SDK keeps conversion events in an in-process queue until they are explicitly flushed.
Call:
core.flush()
to synchronously deliver queued tracking events.
When your application is finished using the SDK, release transport resources with:
core.close()
Example:
core.flush()
core.close()
Why Flush Matters
There is no automatic flush by default.
Queued events remain in memory until one of the following occurs:
core.flush()is called- the configured
batch_sizethreshold is reached auto_flush_interval_msis configured and the timer fires
If your application exits before queued events are flushed, those events are lost.
This is especially important for:
- CLI scripts
- scheduled jobs
- serverless functions
- one-off migration scripts
- test runners
Complete Direct Configuration Example
The following example initializes the SDK using direct configuration, creates a visitor context, runs an experiment, tracks a conversion, flushes queued events, and closes the SDK.
from convert_sdk import (
Core,
SDKConfig,
ConversionStatus,
)
config_data = {
"account_id": "100123",
"project": {"id": "200456"},
"experiences": [
{
"id": "e1",
"key": "checkout-experiment",
"variations": [
{
"id": "v1",
"key": "control",
"traffic_allocation": 50.0,
},
{
"id": "v2",
"key": "treatment",
"traffic_allocation": 50.0,
},
],
}
],
"goals": [
{
"id": "g1",
"key": "purchase_completed",
}
],
}
core = Core(
SDKConfig(data=config_data)
).initialize()
context = core.create_context(
"visitor-001",
visitor_attributes={
"country": "US",
"plan": "pro",
},
)
result = context.run_experience(
"checkout-experiment"
)
if result is not None:
print(
"Variation:",
result.variation_key,
)
conversion = context.track_conversion(
"purchase_completed",
revenue=49.99,
)
assert conversion.status is ConversionStatus.QUEUED
core.flush()
core.close()
7. Remote Initialization (SDK Key)
For production environments, initialize the SDK using your SDK Key.
Unlike Direct Configuration, this downloads the latest configuration from the Convert CDN over HTTPS.
import os
from convert_sdk import (
Core,
SDKConfig,
)
core = Core(
SDKConfig(
sdk_key=os.environ["CONVERT_SDK_KEY"]
)
).initialize()
context = core.create_context(
"visitor-001"
)
result = context.run_experience(
"checkout-experiment"
)
if result is not None:
print(result.variation_key)
core.flush()
core.close()
Never hard-code SDK Keys inside your application.
Instead, load them from:
- environment variables
- secret managers
- deployment configuration
Remote Initialization Behavior
When initialized with:
SDKConfig(
sdk_key="..."
)
the SDK:
- downloads configuration over HTTPS
- caches a configuration snapshot
- performs all visitor evaluations locally
Only the initialization step requires network connectivity.
After configuration has been loaded:
- experience evaluation
- visitor bucketing
- conversion tracking
all execute locally.
Initialization Errors
If configuration cannot be downloaded:
Core(...).initialize()
raises:
ConfigLoadError
Applications should handle this appropriately during startup.
Unlike run_experience() or track_conversion(), configuration loading failures are considered exceptional.
8. Context Manager Pattern
The SDK implements Python's context manager protocol.
This is the recommended approach for:
- scripts
- automation
- command-line tools
- short-lived processes
Example:
from convert_sdk import (
Core,
SDKConfig,
)
with Core(
SDKConfig(data=config_data)
).initialize() as core:
context = core.create_context(
"visitor-001"
)
result = context.run_experience(
"checkout-experiment"
)
if result is not None:
print(result.variation_key)
When execution leaves the block:
- queued events are flushed
- transport resources are closed automatically
Even if an exception occurs inside the block, cleanup still happens.
9. Backend and Front-End Implementation Considerations
The Python SDK performs experiment decisions on the backend.
Many Python applications use this decision to influence what the frontend ultimately receives.
Pattern A: Server-Side Rendering
For Django or Flask applications:
result = context.run_experience(
"homepage-redesign"
)
if result is None:
return render_template(
"homepage_default.html"
)
if result.variation_key == "treatment":
return render_template(
"homepage_treatment.html"
)
return render_template(
"homepage_default.html"
)
The browser immediately receives the correct HTML.
Advantages include:
- no client-side flicker
- consistent rendering
- SEO-friendly pages
- backend-controlled experimentation
Pattern B: Backend Decision + Frontend Behavior
Sometimes Python decides the variation while JavaScript handles interactive behavior.
Example:
result = context.run_experience(
"homepage-redesign"
)
variation = (
result.variation_key
if result
else "control"
)
return render_template(
"homepage.html",
variation=variation,
)
Then expose the assignment:
<script>
window.convertVariation = "";
</script>
Your frontend JavaScript can then react without performing a second experiment evaluation.
Pattern C: API-Driven Applications
For REST APIs:
return {
"variation":
result.variation_key
if result
else "control"
}
Native mobile applications or SPAs can then render the appropriate experience.
Avoid Duplicate Bucketing
Avoid evaluating the same experiment independently on:
- backend
- browser
- mobile
unless they intentionally share:
- visitor identifiers
- configuration
- assignment logic
Instead:
- keep one source of truth
- pass variation information downstream
- reuse stable visitor IDs
This ensures visitors receive consistent experiences.
10. QA Checklist
Before deploying your implementation, verify:
- Python 3.9 or newer
- SDK installed successfully
- SDK initializes without errors
core.is_readyreturnsTrue- Visitor contexts use stable visitor IDs
- Visitor attributes are populated correctly
- Experience keys match Convert
- Goal keys match Convert
- Revenue values are correct
- Duplicate conversions behave as expected
core.flush()is called before shutdowncore.close()releases resources- SDK Key is loaded from environment variables (production)
- Frontend receives the expected variation when applicable
11. Troubleshooting
run_experience() Always Returns None
Check:
- experience key exists
- visitor qualifies
- configuration loaded successfully
- SDK initialized correctly
Remember that None is a normal outcome—not an exception.
Conversion Not Recorded
Verify:
- goal key exists
- visitor context created successfully
- conversion wasn't deduplicated
core.flush()executed
Unknown goal keys return:
ConversionStatus.GOAL_NOT_FOUND
rather than raising an exception.
Events Never Reach Convert
Remember:
core.flush()
must be called unless your application reaches the configured batching threshold or auto-flush interval.
For scripts and serverless environments, always flush before exit.
Configuration Download Fails
If using:
SDKConfig(
sdk_key=...
)
verify:
- SDK Key is valid
- outbound HTTPS connectivity exists
- CDN access is allowed
Initialization raises ConfigLoadError if configuration cannot be loaded.
Conclusion
The Convert Python SDK provides a fast and flexible way to run Full Stack experiments and feature flags from Python applications.
Use Direct Configuration for local development, testing, CI pipelines, and offline tooling where no network access is required. For production, initialize the SDK with your SDK Key to download the latest configuration from the Convert CDN.
Create one visitor context per visitor, evaluate experiences locally, track conversions synchronously, and remember to flush queued events before your application exits.
For frontend-facing implementations, keep one source of truth for experiment assignment and pass variation information to downstream applications rather than re-evaluating the same experiment multiple times.