Skip to content
Codeskop

Core concepts

A short tour of the ideas that both SDKs share. Knowing these makes every other page easier to follow.

Ingest keys

Every project in the dashboard has keys. Your app uses exactly one kind: the public ingest key.

  • Public keys (cs_live_pk_…, cs_test_pk_…) can only send events. They can't read any data, so they're safe to ship inside an APK or a JavaScript bundle.
  • Secret keys (cs_…_sk_…) must never be in an app. Both SDKs refuse a secret key and simply stay switched off.

live and test keys belong to different environments. Use a test key in development and CI, and a live key in production builds, so test traffic never mixes with real users.

A malformed or secret key doesn't throw an error; the SDK stays quietly inactive. If you're seeing no events at all, check the key first.

Events

Everything the SDK sends is an event: a small record with a type, a severity, a timestamp, and context about the device, app and user. These are the types you'll see:

TypePlatformsWhat it means
crashAndroidAn uncaught exception that ended the app.
crash_nativeAndroidA native (C/C++) crash.
anrAndroidAn Application Not Responding freeze.
exceptionAndroid, WebA handled error you reported, or an uncaught JavaScript error or rejection on the web.
api_errorAndroid, WebA request that failed: a network error or an HTTP status of 400 or above.
api_timingAndroid, WebHow long a request took. High-volume and low-severity.
heartbeatAndroid, WebA periodic "still here" signal sent while the app is in the foreground.

Identity

Codeskop tells users apart in two layers:

  • Install ID: a random, anonymous ID created the first time the SDK runs. It's stored on the device (in the browser's localStorage, or a cookie as a fallback) and survives restarts.
  • User ID: your own ID for the signed-in user, set with identify(userId). Call it on every login; calling it again with the same ID is expected and never creates a duplicate user.

Call reset() on logout. The user ID is cleared and events become anonymous again; the install ID stays.

On Android the user ID is kept in memory only, so call identify again on each app launch once you know who's signed in, not just at the moment of login.

Use an opaque ID

Pass the ID from your database or auth provider, not an email address, phone number or name.

Sampling

Some events are high-volume and low-value one by one, mainly api_timing. Sampling keeps a percentage of those to control volume.

  • Android: sample rates come from CodeskopConfig.sampleRates and can be overridden remotely. Crashes and ANRs are always kept.
  • Web: the web SDK currently keeps every event. The sampleRates option is accepted but not applied yet.

The offline queue

Events are written to a queue on the device before anything is sent. The SDK sends them in compressed batches when there's a connection, and keeps anything that wasn't accepted to retry later. A crash on a train with no signal still reaches you.

  • Android: a SQLite-backed queue (10 MB by default). WorkManager sends it about every 15 minutes while there's a connection, and right away when the device reconnects.
  • Web: an IndexedDB queue (5 MB by default), falling back to memory where IndexedDB isn't available. When the tab is hidden, remaining events are sent with sendBeacon so closing a tab doesn't lose them.

If the queue fills up, the oldest routine events (like timings and heartbeats) are dropped first; crashes and errors are protected. More in Offline & Background Sync.

Remote config and the kill-switch

When the SDK starts, it fetches a small configuration from Codeskop. You change it per project in the dashboard (Settings → SDK settings), without shipping a new release:

  • turn capture off completely (the kill-switch),
  • turn network monitoring and ANR detection on or off,
  • lower the request timing sample rate and the offline queue size, within your plan's limits.

The config is fetched once each time the SDK starts, so a change (including the kill-switch) takes effect on the next app launch or page load. If the fetch fails, the SDK uses the last configuration it saw, or safe defaults on a first run. An inactive plan also arrives as "capture off", so an app on an expired plan sends nothing. See Remote Config.

Releases

Every event carries the version of your app that produced it, so you can see when an issue started.

  • Android: the version name and code are read from your app automatically.
  • Web: pass release to init, for example from your build's version.

Built to never hurt your app

Both SDKs make the same promises:

Never throws

Every public method is guarded. A failure inside the SDK is swallowed. It never reaches your code, so there's no need to wrap calls in try/catch.

Safe before init

Calls made before the SDK is initialized do nothing. You don't need to guard them.

Non-blocking

No method does network or heavy disk work on the calling thread. Initialization returns immediately.

Next steps