Skip to content
This repository was archived by the owner on Jul 28, 2022. It is now read-only.

Commit 8caa194

Browse files
committed
Add URL event/user attribute
1 parent 5b6c97f commit 8caa194

File tree

6 files changed

+126
-30
lines changed

6 files changed

+126
-30
lines changed

android/src/main/java/tech/bam/RNBatchPush/RNBatchModule.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,6 @@
1010
import androidx.annotation.NonNull;
1111
import androidx.annotation.Nullable;
1212

13-
import android.util.Log;
14-
1513
import com.batch.android.Batch;
1614
import com.batch.android.BatchActivityLifecycleHelper;
1715
import com.batch.android.BatchEventDispatcher;
@@ -37,6 +35,7 @@
3735
import com.facebook.react.bridge.WritableNativeMap;
3836
import com.facebook.react.modules.core.DeviceEventManagerModule;
3937

38+
import java.net.URI;
4039
import java.util.Date;
4140
import java.util.EnumSet;
4241
import java.util.HashMap;
@@ -518,6 +517,10 @@ public void userData_save(ReadableArray actions) {
518517
long timestamp = (long) action.getDouble("value");
519518
Date date = new Date(timestamp);
520519
editor.setAttribute(key, date);
520+
} else if (type.equals("setURLAttribute")) {
521+
String key = action.getString("key");
522+
String url = action.getString("value");
523+
editor.setAttribute(key, URI.create(url));
521524
} else if (type.equals("removeAttribute")) {
522525
String key = action.getString("key");
523526
editor.removeAttribute(key);

android/src/main/java/tech/bam/RNBatchPush/RNUtils.java

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package tech.bam.RNBatchPush;
22

33
import androidx.annotation.Nullable;
4+
45
import android.util.Log;
56

67
import com.batch.android.BatchEventData;
@@ -13,32 +14,31 @@
1314
import com.facebook.react.bridge.WritableNativeMap;
1415

1516
import org.json.JSONArray;
16-
import org.json.JSONException;
17-
import org.json.JSONObject;
1817

19-
import java.lang.reflect.Array;
20-
import java.util.Iterator;
18+
import java.net.URI;
2119
import java.util.Map;
2220

2321
public class RNUtils {
2422
public static WritableMap convertMapToWritableMap(Map<String, Object> input) {
2523
WritableMap output = new WritableNativeMap();
2624

27-
for(Map.Entry<String, Object> entry: input.entrySet()){
25+
for (Map.Entry<String, Object> entry : input.entrySet()) {
2826
String key = entry.getKey();
2927
Object value = entry.getValue();
3028
if (value instanceof Map) {
3129
output.putMap(key, convertMapToWritableMap((Map<String, Object>) value));
3230
} else if (value instanceof JSONArray) {
33-
output.putArray(key, convertArrayToWritableArray((Object[])value));
34-
} else if (value instanceof Boolean) {
31+
output.putArray(key, convertArrayToWritableArray((Object[]) value));
32+
} else if (value instanceof Boolean) {
3533
output.putBoolean(key, (Boolean) value);
36-
} else if (value instanceof Integer) {
34+
} else if (value instanceof Integer) {
3735
output.putInt(key, (Integer) value);
38-
} else if (value instanceof Double) {
36+
} else if (value instanceof Double) {
3937
output.putDouble(key, (Double) value);
40-
} else if (value instanceof String) {
38+
} else if (value instanceof String) {
4139
output.putString(key, (String) value);
40+
} else if (value instanceof URI) {
41+
output.putString(key, value.toString());
4242
} else {
4343
output.putString(key, value.toString());
4444
}
@@ -53,16 +53,18 @@ public static WritableArray convertArrayToWritableArray(Object[] input) {
5353
Object value = input[i];
5454
if (value instanceof Map) {
5555
output.pushMap(convertMapToWritableMap((Map<String, Object>) value));
56-
} else if (value instanceof JSONArray) {
56+
} else if (value instanceof JSONArray) {
5757
output.pushArray(convertArrayToWritableArray((Object[]) value));
58-
} else if (value instanceof Boolean) {
58+
} else if (value instanceof Boolean) {
5959
output.pushBoolean((Boolean) value);
60-
} else if (value instanceof Integer) {
60+
} else if (value instanceof Integer) {
6161
output.pushInt((Integer) value);
62-
} else if (value instanceof Double) {
62+
} else if (value instanceof Double) {
6363
output.pushDouble((Double) value);
64-
} else if (value instanceof String) {
64+
} else if (value instanceof String) {
6565
output.pushString((String) value);
66+
} else if (value instanceof URI) {
67+
output.pushString(value.toString());
6668
} else {
6769
output.pushString(value.toString());
6870
}
@@ -89,7 +91,6 @@ public static BatchEventData convertSerializedEventDataToEventData(@Nullable Rea
8991
while (iterator.hasNextKey()) {
9092
String key = iterator.nextKey();
9193
ReadableMap valueMap = attributes.getMap(key);
92-
9394
String type = valueMap.getString("type");
9495
if ("string".equals(type)) {
9596
batchEventData.put(key, valueMap.getString("value"));
@@ -99,6 +100,8 @@ public static BatchEventData convertSerializedEventDataToEventData(@Nullable Rea
99100
batchEventData.put(key, valueMap.getDouble("value"));
100101
} else if ("float".equals(type)) {
101102
batchEventData.put(key, valueMap.getDouble("value"));
103+
} else if ("url".equals(type)) {
104+
batchEventData.put(key, URI.create(valueMap.getString("value")));
102105
} else {
103106
Log.e("RNBatchPush", "Invalid parameter : Unknown event_data.attributes type (" + type + ")");
104107
}

ios/RNBatch.m

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,11 @@ - (NSDictionary*) dictionaryWithEventDispatcherPayload:(id<BatchEventDispatcherP
232232
[editor setAttribute:date forKey:action[@"key"]];
233233
}
234234

235+
else if([type isEqualToString:@"setURLAttribute"]) {
236+
NSURL *url = [NSURL URLWithString:[self safeNilValue:action[@"value"]]];
237+
[editor setAttribute:url forKey:action[@"key"]];
238+
}
239+
235240
else if([type isEqualToString:@"removeAttribute"]) {
236241
[editor removeAttributeForKey:action[@"key"]];
237242
}
@@ -352,6 +357,13 @@ - (NSDictionary*) dictionaryWithEventDispatcherPayload:(id<BatchEventDispatcherP
352357
return;
353358
}
354359
[batchEventData putDouble:[(NSNumber*)value doubleValue] forKey:key];
360+
} else if ([@"url" isEqualToString:type]) {
361+
if (![value isKindOfClass:[NSString class]])
362+
{
363+
NSLog(@"RNBatch: Error while tracking event data: event data.attributes: expected string value, got something else");
364+
return;
365+
}
366+
[batchEventData putURL:[NSURL URLWithString:(NSString*) value] forKey:key];
355367
} else {
356368
NSLog(@"RNBatch: Error while tracking event data: Unknown event data.attributes type");
357369
return;

src/BatchEventData.test.ts

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@ import { BatchEventData, Consts } from './BatchEventData';
22
import * as Logger from './helpers/Logger';
33

44
describe('BatchEventData', () => {
5+
afterEach(() => {
6+
jest.clearAllMocks();
7+
});
8+
59
it(`handles less than or equal ${Consts.EventDataMaxTags} tags`, () => {
610
const batchEventData = new BatchEventData();
711
const spy = jest.spyOn(Logger, 'Log');
@@ -12,9 +16,7 @@ describe('BatchEventData', () => {
1216

1317
expect(spy).not.toHaveBeenCalled();
1418
});
15-
it(`handles less than or equal ${
16-
Consts.EventDataMaxValues
17-
} attributes`, () => {
19+
it(`handles less than or equal ${Consts.EventDataMaxValues} attributes`, () => {
1820
const batchEventData = new BatchEventData();
1921
const spy = jest.spyOn(Logger, 'Log');
2022

@@ -36,9 +38,7 @@ describe('BatchEventData', () => {
3638

3739
expect(spy).toHaveBeenCalled();
3840
});
39-
it(`skips other attributes after the first ${
40-
Consts.EventDataMaxValues
41-
}`, () => {
41+
it(`skips other attributes after the first ${Consts.EventDataMaxValues}`, () => {
4242
const batchEventData = new BatchEventData();
4343
const spy = jest.spyOn(Logger, 'Log');
4444

@@ -48,6 +48,27 @@ describe('BatchEventData', () => {
4848

4949
batchEventData.put('too_much', 'value');
5050

51+
expect(spy).toHaveBeenCalled();
52+
});
53+
it(`handles an url attribute`, () => {
54+
const batchEventData = new BatchEventData();
55+
const spy = jest.spyOn(Logger, 'Log');
56+
57+
batchEventData.putURL('test_url', 'https://batch.com');
58+
59+
expect(spy).not.toHaveBeenCalled();
60+
});
61+
it(`skips a too long url attribute`, () => {
62+
const batchEventData = new BatchEventData();
63+
const spy = jest.spyOn(Logger, 'Log');
64+
65+
batchEventData.putURL(
66+
'test_url',
67+
`https://batch.com?${Array(2048)
68+
.fill(1)
69+
.join()}`
70+
);
71+
5172
expect(spy).toHaveBeenCalled();
5273
});
5374
});

src/BatchEventData.ts

Lines changed: 48 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,15 @@ export const Consts = {
66
EventDataMaxTags: 10,
77
EventDataMaxValues: 15,
88
EventDataStringMaxLength: 64,
9+
EventDataURLMaxLength: 2048,
910
};
1011

1112
export enum TypedEventAttributeType {
1213
String = 'string',
1314
Boolean = 'boolean',
1415
Integer = 'integer',
1516
Float = 'float',
17+
URL = 'url',
1618
}
1719

1820
export interface ITypedEventAttribute {
@@ -69,10 +71,10 @@ export class BatchEventData {
6971
return this;
7072
}
7173

72-
public put(key: string, value: string | number | boolean): BatchEventData {
74+
private checkBeforePuttingAttribute(key: string, value: any): void {
7375
if (!isString(key)) {
7476
Log(false, 'BatchEventData - Key must be a string');
75-
return this;
77+
throw new Error();
7678
}
7779

7880
if (!Consts.AttributeKeyRegexp.test(key || '')) {
@@ -82,16 +84,14 @@ export class BatchEventData {
8284
key +
8385
"'"
8486
);
85-
return this;
87+
throw new Error();
8688
}
8789

8890
if (typeof value === 'undefined' || value === null) {
8991
Log(false, 'BatchEventData - Value cannot be undefined or null');
90-
return this;
92+
throw new Error();
9193
}
9294

93-
key = key.toLowerCase();
94-
9595
if (
9696
Object.keys(this._attributes).length >= Consts.EventDataMaxValues &&
9797
!this._attributes.hasOwnProperty(key)
@@ -104,6 +104,48 @@ export class BatchEventData {
104104
key +
105105
"'"
106106
);
107+
throw new Error();
108+
}
109+
}
110+
111+
private prepareAttributeKey(key: string) {
112+
return key.toLowerCase();
113+
}
114+
115+
public putURL(key: string, url: string): BatchEventData {
116+
key = this.prepareAttributeKey(key);
117+
try {
118+
this.checkBeforePuttingAttribute(key, url);
119+
} catch {
120+
return this;
121+
}
122+
123+
if (url.length > Consts.EventDataURLMaxLength) {
124+
Log(
125+
false,
126+
"BatchEventData - Event data can't be longer than " +
127+
Consts.EventDataURLMaxLength +
128+
" characters. Ignoring event data value '" +
129+
url +
130+
"'."
131+
);
132+
return this;
133+
}
134+
135+
this._attributes[key] = {
136+
type: TypedEventAttributeType.URL,
137+
value: url,
138+
};
139+
140+
return this;
141+
}
142+
143+
public put(key: string, value: string | number | boolean): BatchEventData {
144+
key = this.prepareAttributeKey(key);
145+
146+
try {
147+
this.checkBeforePuttingAttribute(key, value);
148+
} catch {
107149
return this;
108150
}
109151

src/BatchUserEditor.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,12 @@ interface IUserSettingsSetDateAttributeAction {
2222
value: number;
2323
}
2424

25+
interface IUserSettingsSetURLAttributeAction {
26+
type: 'setURLAttribute';
27+
key: string;
28+
value: string;
29+
}
30+
2531
interface IUserSettingsSetLanguageAction {
2632
type: 'setLanguage';
2733
value?: string;
@@ -63,6 +69,7 @@ type IUserSettingsAction =
6369
| IUserSettingsRemoveAttributeAction
6470
| IUserSettingsClearAttributesAction
6571
| IUserSettingsSetDateAttributeAction
72+
| IUserSettingsSetURLAttributeAction
6673
| IUserSettingsSetIdentifierAction
6774
| IUserSettingsSetLanguageAction
6875
| IUserSettingsSetRegionAction
@@ -104,6 +111,14 @@ export class BatchUserEditor {
104111
});
105112
}
106113

114+
public setURLAttribute(key: string, value: string) {
115+
return this.addAction({
116+
type: 'setURLAttribute',
117+
key,
118+
value,
119+
});
120+
}
121+
107122
public removeAttribute(key: string) {
108123
return this.addAction({
109124
type: 'removeAttribute',

0 commit comments

Comments
 (0)