playtesters_sdk

Drop this into the Android or iOS app you're testing through Playtesters to wire up the three ingest calls without touching HTTP directly.

Setup

import 'package:playtesters_sdk/playtesters_sdk.dart';

await Playtesters.configure(apiKey: 'ak_your_app_key');

Call this once, early — e.g. in main() before runApp. There's no base URL to configure — the SDK already points at the Playtesters server.

Getting a code onto the device

Call this once your first screen builds — it does everything: checks whether the app owner has the tester dialog turned on at all, tries the Play Store Install Referrer automatically, and only falls back to the built-in code-entry dialog if that comes up empty. It's a no-op if a code is already registered, so it's safe to call on every app start:

await Playtesters.checkTestSession(context);

Install Referrer is Android/Play Store only — on iOS this always falls straight through to the dialog. If you'd rather drive each step yourself (e.g. to show your own UI instead of the built-in dialog), readReferrer(), isDialogEnabled(), showCodeDialog() and registerUser() are all still available individually — see the source doc comments on each.

registerUser's userId is optional and just for your own bookkeeping — omit it and the SDK uses whatever identify() was called with, or a random id it generates and persists itself; either way it has no bearing on whether registration succeeds.

Identifying your own users

Playtesters.identify(myOwnUserId);

Call this once your app's own login completes. Every log/achieved call made afterward carries identified_user_id in its data, so you can trace a Playtesters log entry back to one of your own accounts later.

Showing testers they're being tracked

const PlaytestersBadge()

Drop this widget anywhere in your tree — it fetches on its own and renders nothing until it has something to show, and nothing at all if the campaign owner turned this off (each campaign has a "Dev mode" switch in the Playtesters app). Build your own UI on Playtesters.fetchSessionInfo() directly if you want different visuals; check .visible before showing anything.

Logging

await Playtesters.log({'screen': 'checkout'});
await Playtesters.achieved({'screen': 'checkout', 'note': 'purchase completed'});

Both work with or without a registered code — call them from anywhere in the app, for every user, not just testers who entered a code. If a code was registered via registerUser, both automatically attach it (so the entry counts toward that tester's session); if not, they still send package, version_name, version_code, and platform ("android" or "ios"), just with no tester/session attached — useful for seeing where regular (non-tester) users go in the app, from the Playtesters dashboard's app-level log view. log never awards credit; achieved is the one that counts a test day for the tester, but only when called with a real code attached (once per day, decided server-side). Put achieved behind whatever screen you consider "the tester did the thing".

Verifying the integration

The Playtesters app won't let a developer open a campaign for an app until its SDK integration has proven itself once. Call this once while you're wiring things up — before you even have a real tester code:

await Playtesters.verifyIntegration();

It's the exact same call as achieved({}), just with no code registered yet; the backend records that a real request reached it with this app's key and flips the app to verified. No need to remove this call afterwards — achieved calls with a real code behave normally regardless of whether verification already happened.

Libraries

playtesters_sdk
Client SDK for wiring an Android or iOS Flutter app into the Playtesters closed-testing platform.