Skip to content

Commit a1e497d

Browse files
feat: proposed changes
Correct documentation in the README. Remove `OptableTraits` and use simple data structures. Fix sending GAID when limited tracking. Fix regexp. Remove unused `OptableResponse`.
1 parent 5342ef8 commit a1e497d

17 files changed

Lines changed: 144 additions & 258 deletions

File tree

DemoApp/DemoAppJava/app/src/main/java/co/optable/demoappjava/ui/GamBannerFragment.java

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,10 @@
88
import androidx.annotation.NonNull;
99
import androidx.annotation.Nullable;
1010
import androidx.fragment.app.Fragment;
11-
import co.optable.android_sdk.*;
11+
import co.optable.android_sdk.OptableIdentifier;
12+
import co.optable.android_sdk.OptableResult;
13+
import co.optable.android_sdk.OptableSDK;
14+
import co.optable.android_sdk.OptableTargeting;
1215
import co.optable.demoappjava.R;
1316
import co.optable.demoappjava.TheApplication;
1417
import com.google.android.gms.ads.admanager.AdManagerAdRequest;
@@ -121,8 +124,7 @@ private void profile() {
121124
traits.put("hasAccount", true);
122125
traits.put("sampleFloat", 0.75);
123126

124-
OptableTraits traitsRequest = new OptableTraits(traits, "c:12", Set.of("c:id1", "c:id2"));
125-
optable.profile(traitsRequest, result -> {
127+
optable.profile(traits, "c:12", Set.of("c:id1", "c:id2"), result -> {
126128
if (result instanceof OptableResult.Success) {
127129
appendStatusText("Profile success");
128130
} else if (result instanceof OptableResult.Error<OptableTargeting> error) {
@@ -154,4 +156,4 @@ private void appendStatusText(@NonNull String message) {
154156
statusTextView.append("\n\n" + message);
155157
}
156158

157-
}
159+
}

DemoApp/DemoAppJava/app/src/main/java/co/optable/demoappjava/ui/PrebidBannerFragment.java

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,10 @@
88
import androidx.annotation.NonNull;
99
import androidx.annotation.Nullable;
1010
import androidx.fragment.app.Fragment;
11-
import co.optable.android_sdk.*;
11+
import co.optable.android_sdk.OptableIdentifier;
12+
import co.optable.android_sdk.OptableResult;
13+
import co.optable.android_sdk.OptableSDK;
14+
import co.optable.android_sdk.OptableTargeting;
1215
import co.optable.demoappjava.R;
1316
import co.optable.demoappjava.TheApplication;
1417
import com.google.android.gms.ads.AdListener;
@@ -175,8 +178,7 @@ private void profile() {
175178
traits.put("hasAccount", true);
176179
traits.put("sampleFloat", 0.75);
177180

178-
OptableTraits traitsRequest = new OptableTraits(traits, "c:12", Set.of("c:id1", "c:id2"));
179-
optable.profile(traitsRequest, result -> {
181+
optable.profile(traits, "c:12", Set.of("c:id1", "c:id2"), result -> {
180182
if (result instanceof OptableResult.Success) {
181183
appendStatusText("Profile Success");
182184
} else if (result instanceof OptableResult.Error<OptableTargeting> error) {
@@ -208,4 +210,4 @@ private void appendStatusText(@NonNull String message) {
208210
statusTextView.append("\n\n" + message);
209211
}
210212

211-
}
213+
}

DemoApp/DemoAppKotlin/app/src/main/java/co/optable/androidsdkdemo/ui/GamBannerFragment.kt

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,10 @@ import android.view.ViewGroup
77
import android.widget.Button
88
import android.widget.TextView
99
import androidx.fragment.app.Fragment
10-
import co.optable.android_sdk.*
10+
import co.optable.android_sdk.OptableIdentifier
11+
import co.optable.android_sdk.OptableResult
12+
import co.optable.android_sdk.OptableSDK
13+
import co.optable.android_sdk.OptableTargeting
1114
import co.optable.androidsdkdemo.R
1215
import co.optable.androidsdkdemo.TheApplication
1316
import com.google.android.gms.ads.admanager.AdManagerAdRequest
@@ -126,8 +129,7 @@ class GamBannerFragment : Fragment() {
126129
"sampleFloat" to 0.75,
127130
)
128131

129-
val traitsRequest = OptableTraits(traits, "c:12", setOf("c:id1", "c:id2"))
130-
optable.profile(traitsRequest) { result ->
132+
optable.profile(traits, "c:12", setOf("c:id1", "c:id2")) { result ->
131133
when (result) {
132134
is OptableResult.Success<*> -> {
133135
appendStatusText("Profile success")
@@ -166,4 +168,4 @@ class GamBannerFragment : Fragment() {
166168
statusTextView.append("\n\n$message")
167169
}
168170

169-
}
171+
}

DemoApp/DemoAppKotlin/app/src/main/java/co/optable/androidsdkdemo/ui/PrebidBannerFragment.kt

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,10 @@ import android.view.ViewGroup
1111
import android.widget.Button
1212
import android.widget.TextView
1313
import androidx.fragment.app.Fragment
14-
import co.optable.android_sdk.*
14+
import co.optable.android_sdk.OptableIdentifier
15+
import co.optable.android_sdk.OptableResult
16+
import co.optable.android_sdk.OptableSDK
17+
import co.optable.android_sdk.OptableTargeting
1518
import co.optable.androidsdkdemo.R
1619
import co.optable.androidsdkdemo.TheApplication
1720
import com.google.android.gms.ads.AdListener
@@ -187,8 +190,7 @@ class PrebidBannerFragment : Fragment() {
187190
"sampleFloat" to 0.75,
188191
)
189192

190-
val traitsRequest = OptableTraits(traits, "c:12", setOf("c:id1", "c:id2"))
191-
optable.profile(traitsRequest) { result ->
193+
optable.profile(traits, "c:12", setOf("c:id1", "c:id2")) { result ->
192194
when (result) {
193195
is OptableResult.Success -> {
194196
appendStatusText("Profile success")
@@ -225,4 +227,4 @@ class PrebidBannerFragment : Fragment() {
225227
statusTextView.append("\n\n$message")
226228
}
227229

228-
}
230+
}

README.md

Lines changed: 58 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -159,58 +159,49 @@ Sensitive data as email and phone number encrypted using SHA256.
159159
#### Kotlin
160160

161161
```kotlin
162-
val ids = OptableIdentifiers(
163-
email = "john.doe+test@example.com",
164-
phoneNumber = "+1(555)1234567",
165-
postalCode = "12345",
166-
ipv4Address = "192.168.0.1",
167-
ipv6Address = "2001:db8::1",
168-
appleIdfa = "a1b2c3d4-e5f6-7890-abcd-ef0123456789",
169-
googleGaid = "38400000-8cf0-11bd-b23e-10b96e40000d",
170-
rokuRida = "roku-rida-123",
171-
samsungTifa = "tifaabc",
172-
amazonFireAfai = "afaixyz",
173-
netId = "netid123",
174-
id5 = "id5token",
175-
utiq = "utiqvalue",
176-
custom = mapOf(
177-
"v" to "vidvalue",
178-
"c1" to "custom one"
179-
),
180-
raw = listOf("raw:alreadyEncoded", "ultra:someRawValue")
162+
val ids = listOf(
163+
OptableIdentifier.Email("john.doe+test@example.com"),
164+
OptableIdentifier.PhoneNumber("+1(555)1234567"),
165+
OptableIdentifier.PostalCode("12345"),
166+
OptableIdentifier.IPv4("192.168.0.1"),
167+
OptableIdentifier.IPv6("2001:db8::1"),
168+
OptableIdentifier.AppleIdfa("a1b2c3d4-e5f6-7890-abcd-ef0123456789"),
169+
OptableIdentifier.GoogleGaid("38400000-8cf0-11bd-b23e-10b96e40000d"),
170+
OptableIdentifier.RokuRida("roku-rida-123"),
171+
OptableIdentifier.SamsungTifa("tifaabc"),
172+
OptableIdentifier.AmazonFireAfai("afaixyz"),
173+
OptableIdentifier.NetId("netid123"),
174+
OptableIdentifier.ID5("id5token"),
175+
OptableIdentifier.Utiq("utiqvalue"),
176+
OptableIdentifier.Custom("v", "vidvalue"),
177+
OptableIdentifier.Custom("c1", "custom one"),
178+
OptableIdentifier.Raw("raw:alreadyEncoded"),
179+
OptableIdentifier.Raw("ultra:someRawValue")
181180
)
182181
```
183182

184183
#### Java
185184

186-
You can use the Builder pattern for Java implementation.
187-
188185
```java
189-
OptableIdentifiers ids = new OptableIdentifiers.Builder()
190-
.email("john.doe+test@example.com")
191-
.phoneNumber("+1(555)1234567")
192-
.postalCode("12345")
193-
.ipv4Address("192.168.0.1")
194-
.ipv6Address("2001:db8::1")
195-
.appleIdfa("a1b2c3d4-e5f6-7890-abcd-ef0123456789")
196-
.googleGaid("38400000-8cf0-11bd-b23e-10b96e40000d")
197-
.rokuRida("roku-rida-123")
198-
.samsungTifa("tifaabc")
199-
.amazonFireAfai("afaixyz")
200-
.netId("netid123")
201-
.id5("id5token")
202-
.utiq("utiqvalue")
203-
.custom(Map.of("v", "vidvalue", "c1", "custom one"))
204-
.raw(List.of("raw:alreadyEncoded", "ultra:someRawValue"))
205-
.build();
206-
```
207-
208-
Additionally, you can set automatic fetching GAID if it is available. It will be ignored if `googleGaid` is set.
209-
210-
```kotlin
211-
val ids = OptableIdentifiers(
212-
receiveGaidAutomatically = true
213-
)
186+
ArrayList<OptableIdentifier> ids = Lists.newArrayList(
187+
new OptableIdentifier.Email("john.doe+test@example.com"),
188+
new OptableIdentifier.PhoneNumber("+1(555)1234567"),
189+
new OptableIdentifier.PostalCode("12345"),
190+
new OptableIdentifier.IPv4("192.168.0.1"),
191+
new OptableIdentifier.IPv6("2001:db8::1"),
192+
new OptableIdentifier.AppleIdfa("a1b2c3d4-e5f6-7890-abcd-ef0123456789"),
193+
new OptableIdentifier.GoogleGaid("38400000-8cf0-11bd-b23e-10b96e40000d"),
194+
new OptableIdentifier.RokuRida("roku-rida-123"),
195+
new OptableIdentifier.SamsungTifa("tifaabc"),
196+
new OptableIdentifier.AmazonFireAfai("afaixyz"),
197+
new OptableIdentifier.NetId("netid123"),
198+
new OptableIdentifier.ID5("id5token"),
199+
new OptableIdentifier.Utiq("utiqvalue"),
200+
new OptableIdentifier.Custom("v", "vidvalue"),
201+
new OptableIdentifier.Custom("c1", "custom one"),
202+
new OptableIdentifier.Raw("raw:alreadyEncoded"),
203+
new OptableIdentifier.Raw("ultra:someRawValue")
204+
);
214205
```
215206

216207
### Identify API
@@ -221,9 +212,9 @@ the Google Advertising ID, or even your own vendor or app level `PPID`, you can
221212
#### Kotlin
222213

223214
```kotlin
224-
val ids = OptableIdentifiers(
225-
email = "some.email@address.com",
226-
raw = listOf("c:my-id-123")
215+
val ids = listOf(
216+
OptableIdentifier.Email("john.doe+test@example.com"),
217+
OptableIdentifier.PhoneNumber("+1(555)1234567")
227218
)
228219
optable.identify(ids) { result ->
229220
val msg = when (result) {
@@ -237,10 +228,10 @@ optable.identify(ids) { result ->
237228
#### Java
238229

239230
```java
240-
OptableIdentifiers ids = new OptableIdentifiers.Builder()
241-
.email("some.email@address.com")
242-
.raw(Lists.newArrayList("c:my-id-123"))
243-
.build();
231+
ArrayList<OptableIdentifier> ids = Lists.newArrayList(
232+
new OptableIdentifier.Email("john.doe+test@example.com"),
233+
new OptableIdentifier.PhoneNumber("+1(555)1234567")
234+
);
244235
optable.identify(ids, result -> {
245236
if (result instanceof OptableResult.Success) {
246237
Log.d(TAG, "Identify success");
@@ -258,18 +249,6 @@ the `identify()` method on your SDK instance every time you authenticate a user,
258249
example once every 15 to 60 minutes while the application is being actively used and an internet connection is
259250
available.
260251

261-
Alternatively, you can use simplified identify:
262-
263-
```kotlin
264-
optable.identify(email, true, "ppid") { result ->
265-
...
266-
}
267-
```
268-
269-
The second (`sendGoogleAdIDBoolean`) and third (`ppid`) arguments to `identify()` are optional. Since the `gaid` value provided to `identify()` is `true`, the SDK will fetch and send the Google
270-
Advertising ID in the call to `identify` too, unless the user has turned on "Limit ad tracking" in their Google device
271-
advertising settings.
272-
273252

274253
### Profile API
275254

@@ -314,6 +293,12 @@ The specified traits are associated with the user's device and can be used for m
314293
traits are of type `HashMap<String, Any>`, and should consist only of key-value pairs where the key is a string and the value is either a string, number, or
315294
boolean.
316295

296+
Additionally you can provide `id` and `neighbors` to associate the profile with other identifiers. The `id` parameter takes precedence over the passport if provided.
297+
298+
```kotlin
299+
optable.profile(traits, "c:12", setOf("c:id1", "c:id2")) { ... }
300+
```
301+
317302
### Targeting API
318303

319304
To get the targeting key values associated by the configured DCN with the device in real-time, you can call the
@@ -322,7 +307,9 @@ To get the targeting key values associated by the configured DCN with the device
322307
#### Kotlin
323308

324309
```kotlin
325-
val ids = OptableIdentifiers(email = "test@test.com")
310+
val ids = listOf(
311+
OptableIdentifier.Email("test@test.com"),
312+
)
326313
optable.targeting(ids) { result ->
327314
val requestBuilder = AdManagerAdRequest.Builder()
328315

@@ -344,7 +331,9 @@ optable.targeting(ids) { result ->
344331
#### Java
345332

346333
```java
347-
OptableIdentifiers ids = new OptableIdentifiers.Builder().email("test@test.com").build();
334+
ArrayList<OptableIdentifier> ids = Lists.newArrayList(
335+
new OptableIdentifier.Email("test@test.com")
336+
)
348337
optable.targeting(ids, result -> {
349338
if (result instanceof OptableResult.Success<OptableTargeting> success) {
350339
Map<String, List<String>> audiences = success.getData().getAudiences();
@@ -469,7 +458,7 @@ private fun onClickLoadAd() {
469458
private fun applyOptableToGam(builder: AdManagerAdRequest.Builder, targeting: OptableTargeting?) {
470459
if (targeting == null) return
471460

472-
val audiences = targeting.audiences
461+
val audiences = targeting.gamTargetingKeywords
473462
if (audiences != null) {
474463
for (entry in audiences.entries) {
475464
builder.addCustomTargeting(entry.key, entry.value)
@@ -500,7 +489,7 @@ private fun applyOptableToGam(builder: AdManagerAdRequest.Builder, targeting: Op
500489
private void applyOptableToGam(AdManagerAdRequest.Builder builder, @Nullable OptableTargeting targeting) {
501490
if (targeting == null) return;
502491

503-
Map<String, List<String>> audiences = targeting.getAudiences();
492+
Map<String, List<String>> audiences = targeting.getGamTargetingKeywords();
504493
if (audiences != null) {
505494
for (Map.Entry<String, List<String>> entry : audiences.entrySet()) {
506495
builder.addCustomTargeting(entry.getKey(), entry.getValue());

android_sdk/src/main/java/co/optable/android_sdk/OptableResponse.kt

Lines changed: 0 additions & 34 deletions
This file was deleted.

android_sdk/src/main/java/co/optable/android_sdk/OptableResult.kt

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
package co.optable.android_sdk
22

3+
/**
4+
* A generic wrapper for various OptableSDK result types.
5+
* `Success` represents a successful API call with a result.
6+
* `Error` represents an error result with a message.
7+
*/
38
sealed class OptableResult<T> {
49

510
data class Success<T>(
@@ -10,4 +15,4 @@ sealed class OptableResult<T> {
1015
val message: String,
1116
) : OptableResult<T>()
1217

13-
}
18+
}

android_sdk/src/main/java/co/optable/android_sdk/OptableSDK.kt

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,10 +91,22 @@ class OptableSDK(
9191
* Calls the Optable Sandbox "profile" API to associate the
9292
* specified key-value traits, which can be subsequently used for
9393
* audience assembly.
94+
*
95+
* @param traits Contains an object composed of key / values to be associated with the profile.
96+
* Values must be of simple types (String, Int, Boolean, Double) or they will be stringified with `toString`.
97+
* @param id The identifier that traits and neighbors will be linked to. This value takes precedence over the passport if provided.
98+
* @param neighbors An array of identifiers to link to the id or passport
99+
*
94100
*/
95-
fun profile(traits: OptableTraits, listener: OptableResultListener<OptableTargeting>) {
101+
@JvmOverloads
102+
fun profile(
103+
traits: Map<String, Any>,
104+
id: String? = null,
105+
neighbors: Set<String> = emptySet(),
106+
listener: OptableResultListener<OptableTargeting>
107+
) {
96108
scope.launch {
97-
val response = networkClient.profile(traits)
109+
val response = networkClient.profile(traits, id, neighbors)
98110

99111
MainScope().launch {
100112
val optableResult = when (response) {

0 commit comments

Comments
 (0)