Options¶
Pass options once, as a DeaSdkOptions value, when you create the DeaSdk. They are read when the
instance is created and cannot be changed afterwards; to use different options, dispose() the
instance and create a new one.
import DeaBase
import DeaSDK
let dea = DeaSdk(
options: DeaSdkOptions(
appId: "YOUR_APP_ID",
requireConsent: true,
consent: Consent(store: DefaultsConsentStore()),
appKey: "YOUR_APP_KEY",
modelUpdates: true,
events: CaptureEvent.pointerKinds,
motionRate: 50
)
)
dea.start()
Every option except appId has a default, so name only the ones you change. Swift takes the
arguments in the order the initializer declares them: appId, requireConsent, consent,
appKey, registryAppId, onLog, modelDirectory, modelUpdates, modelTimeout, events,
idleMotionMs, motionRate, touchMarginMs.
import DeaBase is only needed when you name Consent, a consent store or CaptureEvent yourself.
Core options¶
appId¶
| Type | Default | Required |
|---|---|---|
String |
— | Yes |
The appId DEA issued for this iOS app. See Accounts and keys.
The addresses the SDK sends requests to are built in: no option changes them.
requireConsent¶
| Type | Default | Required |
|---|---|---|
Bool |
true |
No |
When true, nothing is recorded until the user has agreed. See
User Consent.
Set it to false only when consent is already established outside the SDK — for example, your app
asks during onboarding and creates the DeaSdk only after the user agrees.
consent¶
| Type | Default | Required |
|---|---|---|
Consent? |
nil — the answer is stored in UserDefaults.standard |
No |
Where the user's consent answer is kept. Leave it nil unless your app already keeps consent
somewhere else and wants the SDK to read and write it there. Pass a Consent built over your own
ConsentStore:
import DeaBase
import DeaSDK
final class MyConsentStore: ConsentStore {
func read() -> ConsentDecision {
switch MyPrivacySettings.shared.behaviourMeasurement {
case .some(true): return .granted
case .some(false): return .denied
case .none: return .unknown
}
}
func write(_ decision: ConsentDecision) {
switch decision {
case .granted: MyPrivacySettings.shared.behaviourMeasurement = true
case .denied: MyPrivacySettings.shared.behaviourMeasurement = false
case .unknown: MyPrivacySettings.shared.behaviourMeasurement = nil
}
}
}
let dea = DeaSdk(
options: DeaSdkOptions(
appId: "YOUR_APP_ID",
consent: Consent(store: MyConsentStore()),
appKey: "YOUR_APP_KEY"
)
)
The store is read once, when the Consent is created. Replace MyPrivacySettings with your own
settings storage.
| Store | Keeps the answer |
|---|---|
DefaultsConsentStore() |
In UserDefaults.standard, across launches (the default) |
MemoryConsentStore() |
For this run only. The user is asked again on every launch |
onLog¶
| Type | Default | Required |
|---|---|---|
((LogEntry) -> Void)? |
nil |
No |
Called with each log entry the SDK build carries. The production build of the iOS SDK carries no
log, so onLog is never called there.
Capture options¶
events¶
| Type | Default | Required |
|---|---|---|
[CaptureEvent] |
CaptureEvent.pointerKinds |
No |
The input kinds to capture. Capturing fewer kinds reduces work but also reduces the evidence the score is built on.
| Value | Captures |
|---|---|
.pointerDown |
A finger or stylus touches the screen |
.pointerMove |
A touch moves, and a pointer hovers |
.pointerUp |
A touch ends |
.pointerCancel |
The system cancels a touch |
.wheel |
Trackpad and mouse scrolling |
.keyDown |
A key press your app reports with captureKey |
.keyUp |
A key release your app reports with captureKey |
CaptureEvent.pointerKinds is the first five. Key kinds are not in the default list and are never
captured automatically. Add .keyDown only if your app reports typing — see
Report typing. Without it, captureKey does
nothing.
import DeaBase
import DeaSDK
let dea = DeaSdk(
options: DeaSdkOptions(
appId: "YOUR_APP_ID",
appKey: "YOUR_APP_KEY",
events: CaptureEvent.pointerKinds + [.keyDown]
)
)
Scrolling, hover, and mouse or trackpad pointers are captured but do not add to the score on iOS: the score is built from touches and stylus contacts, device motion, and the key presses your app reports.
motionRate¶
| Type | Default | Required |
|---|---|---|
Int (Hz) |
50 |
No |
The motion sensor rate to request. Values below 25 are raised to 25.
sessionInfo.device.sensorRate reports this rate once the first motion reading has arrived, and
0 until then — for the whole run on the simulator or on a device without motion sensors.
idleMotionMs¶
| Type | Default | Required |
|---|---|---|
Int (ms) |
3000 |
No |
When no one is touching the screen, motion data is kept at a reduced rate — one reading every
idleMotionMs — until the next touch. 0 keeps every reading.
touchMarginMs¶
| Type | Default | Required |
|---|---|---|
Int (ms) |
200 |
No |
Motion data is kept at the full rate for this long before and after each touch, even while idle.
To keep a screen out of the recording, use
pause().
Attestation options¶
App Attest is used automatically when the App Attest capability is added to your app — see Attest.
appKey¶
| Type | Default | Required |
|---|---|---|
String? |
nil |
Yes, for Attest |
The appKey DEA issued with your appId. The SDK sends it in the X-App-Key header when it
registers the device key. Leading and trailing spaces are removed, and an empty string counts as no
key.
Without it, attest() and renewAttestation() answer .unsupported without contacting DEA, and
the result's detail says that no appKey was given. Reading the classification does not need it.
DeaSdk.appKey reads back the key the SDK sends.
registryAppId¶
| Type | Default | Required |
|---|---|---|
String? |
nil |
No |
The appId the SDK writes inside the proofs it signs, which DEA accepts only when it names the app
behind appKey. Set it to your appId. Left nil, proofs carry a built-in development id instead.
Attest and getClassification() do not read it; the proof calls on the
Ads page do.
Model options¶
The SDK scores with a model built into it. With modelUpdates on, it also asks DEA's model server
whether a newer model is published: every time a DeaSdk is created, and when the app returns to
the foreground if a day has passed since the last check that got an answer. It downloads a model
only when it is newer than the one running, and the scoring engine checks the file before using it.
A new model is used at once, even in the middle of a session, and is kept on the device for the
next launch. Checks run in the background: nothing waits for them, and they never throw.
DeaSdk.modelInfo says which model is scoring — see the
API Reference.
modelUpdates¶
| Type | Default | Required |
|---|---|---|
Bool |
true |
No |
Set it to false to stop the checks. Any downloaded model is deleted when the DeaSdk is created,
and the SDK scores with the built-in model.
modelDirectory¶
| Type | Default | Required |
|---|---|---|
URL? |
nil — the app's Application Support directory |
No |
Where downloaded models are kept; the SDK creates dea/models inside it. If that folder cannot be
created, the SDK checks for no updates and scores with the built-in model.
modelTimeout¶
| Type | Default | Required |
|---|---|---|
TimeInterval |
30 seconds |
No |
How long one model request may take before it is abandoned.
Reserved¶
DeaSdkOptions has five more parameters, reserved for DEA's own tooling and tests. Leave them at
their defaults:
| Parameter | What it does |
|---|---|
integrations |
Ignored with a production appId |
modelUrlOverride |
Ignored with a production appId |
openCore |
Replaces the scoring engine |
keystore |
Makes the device key or App Attest refuse, to test those failures |
urlProtocolClasses |
Puts URLProtocol classes in front of every request the SDK makes |