Skip to main content

People (user profiles)

Unified behavior: all people operations go to POST /api/sdk/people/<action> with JSON bodies including siteId and userId (the current distinct id). Rate limits apply per site and user (see backend rateLimits.people). Supported operations align with the browser People reference:
ActionHTTP pathPurpose
Set/people/setMerge properties (overwrite keys)
Set once/people/set_onceSet only if missing
Unset/people/unsetRemove keys
Increment/people/incrementNumeric delta
Append/people/appendAppend to list properties
Union/people/unionSet union on list properties
Remove/people/removeRemove values from lists
Track charge/people/track_chargeRevenue / charge tracking
Clear charges/people/clear_chargesClear charge history
Delete user/people/delete_userDelete profile data for user

Via UserContext

const u = client.forUser('distinct-1');

await u.people.set({ email: '[email protected]', plan: 'pro' });
await u.people.setOnce({ signup_source: 'invite' });
await u.people.increment('login_count', 1);
await u.people.append('roles', ['editor']);
await u.people.union('tags', ['priority']);
await u.people.unset(['temp_field']);
await u.people.trackCharge(49.99, { currency: 'USD' });
await u.people.clearCharges();
// await u.people.deleteUser();

Direct shortcuts on TrodoClient

Node exposes client.people.set(distinctId, props) (and siblings). Python uses people_set, people_increment, etc., on TrodoClient.

Groups (accounts, organizations)

Unified behavior: group membership and group profiles use POST /api/sdk/groups/*. Workflows match Groups (browser).

Membership

const u = client.forUser('user-1');

await u.set_group('company', 'org_123');           // string or string[]
await u.add_group('company', 'org_456');
await u.remove_group('company', 'org_456');
Top-level shortcuts: Node set_group / add_group / remove_group; Python set_group, add_group, remove_group on TrodoClient.

Group profile (scoped object)

Obtained via get_group(groupKey, groupId). Returns a profile object with set, set_once, union, remove, unset, increment, append, delete.
const profile = client
  .forUser('user-1')
  .get_group('company', 'org_123');

await profile.set({ employee_count: 50, name: 'Acme' });
await profile.union('features_enabled', ['sso']);
Python GroupProfile uses snake_case method names (set_once matches the HTTP route segment). Node GroupProfile uses set_once as well (aligned with wire naming).

Auto-events (global error tracking)

When autoEvents: true / auto_events: true is set on the client or you call enableAutoEvents / enable_auto_events, the SDK registers process-wide hooks that send a server_error auto event for uncaught failures.
RuntimeWhat gets hooked
Nodeprocess.on('uncaughtException'), process.on('unhandledRejection')
Pythonsys.excepthook, threading.excepthook (3.8+)
Events use a synthetic distinct id server_global and include runtime: nodejs or runtime: python, plus message and stack fields.
const client = new TrodoClient({ siteId: '...', autoEvents: true });
// or after init:
client.enableAutoEvents();

await client.shutdown(); // removes listeners
You can also toggle auto-events per UserContext with enableAutoEvents / disableAutoEvents (Node) or enable_auto_events / disable_auto_events (Python).

Flush and shutdown

MethodNodePython
Flush queueawait client.flush()client.flush()
Stop timers, flush, disable auto hooksawait client.shutdown()client.shutdown()
Always call shutdown() before terminating the process when batching or auto-events are enabled.

Python async HTTP (advanced)

The trodo-python[async] extra installs httpx and provides AsyncHttpClient in trodo.api.async_client, exposing post_track, post_event, post_bulk_events, post_identify, people/group helpers — same paths and headers as the sync client. There is no separate high-level async TrodoClient in the package today; use AsyncHttpClient if you need async/await at the HTTP layer and wire calls yourself, or run the sync client in a thread pool.

Error handling and retries

  • HTTP clients retry failed requests with exponential backoff on network errors and 5xx responses (see retries in Overview).
  • After retries are exhausted, failures are passed to onError (if set) and may return empty result objects for call sites that expect JSON.
  • Session confirmation (POST /api/sdk/track) failures are treated as non-fatal so your app does not block on analytics.

GDPR and privacy APIs

The write service also exposes GDPR-related routes (/api/sdk/gdpr/*, GET /api/sdk/privacy/policy) for export, delete, and anonymize flows. These are HTTP endpoints rather than first-class methods on trodo-node / trodo-python; call them with your server’s HTTP client if you integrate compliance automation. See Privacy and compliance for product context.