add user profile reporting
This commit is contained in:
parent
4c876831ed
commit
58d0daabc5
34
README.md
34
README.md
@ -31,7 +31,7 @@ AppMetrica.reportEvent('Hello world');
|
||||
```js
|
||||
import AppMetrica from 'react-native-appmetrica';
|
||||
|
||||
// Starts the statistics collection process.
|
||||
// Start the statistics collection process.
|
||||
AppMetrica.activateWithApiKey('...KEY...');
|
||||
// OR
|
||||
AppMetrica.activateWithConfig({
|
||||
@ -40,10 +40,40 @@ AppMetrica.activateWithConfig({
|
||||
firstActivationAsUpdate: true,
|
||||
});
|
||||
|
||||
// Sends a custom event message and additional parameters (optional).
|
||||
// Send a custom event message and additional parameters (optional).
|
||||
AppMetrica.reportEvent('My event');
|
||||
AppMetrica.reportEvent('My event', { foo: 'bar' });
|
||||
|
||||
// Send a custom error event.
|
||||
AppMetrica.reportError('My error');
|
||||
|
||||
// Send user profile with predefined attributes.
|
||||
AppMetrica.reportUserProfile({ name: 'User 1', age: 87 });
|
||||
|
||||
// Send user profile with custom attributes.
|
||||
AppMetrica.reportUserProfile({
|
||||
likesMusic: true,
|
||||
addedToFavorites: '+1',
|
||||
score: 150,
|
||||
});
|
||||
```
|
||||
### Reporting user profile
|
||||
|
||||
All predefined attributes are supported. Use `null` to reset them.
|
||||
|
||||
```js
|
||||
type UserProfileAttributes = {
|
||||
name?: ?string,
|
||||
gender?: 'female' | 'male' | string | void,
|
||||
age?: ?number,
|
||||
birthDate?: Date | [number] | [number, number] | [number, number, number] | void,
|
||||
notificationsEnabled?: boolean,
|
||||
/** custom attributes */
|
||||
[string]: string | number | boolean,
|
||||
};
|
||||
```
|
||||
|
||||
Custom attributes are supported. They can't be reset for now.
|
||||
|
||||
Use values like `'+1'`, `'-10'` for counters. Current limitation is any custom attribute which value started with `'+'` or `'-'` will be considered as a counter.
|
||||
|
||||
|
@ -8,15 +8,23 @@ import android.util.Log;
|
||||
import com.facebook.react.bridge.ReactApplicationContext;
|
||||
import com.facebook.react.bridge.ReactContextBaseJavaModule;
|
||||
import com.facebook.react.bridge.ReactMethod;
|
||||
import com.facebook.react.bridge.ReadableArray;
|
||||
import com.facebook.react.bridge.ReadableMap;
|
||||
import com.facebook.react.bridge.ReadableMapKeySetIterator;
|
||||
|
||||
import java.lang.Exception;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
|
||||
import org.json.JSONObject;
|
||||
|
||||
import com.yandex.metrica.YandexMetrica;
|
||||
import com.yandex.metrica.YandexMetricaConfig;
|
||||
import com.yandex.metrica.profile.UserProfile;
|
||||
import com.yandex.metrica.profile.Attribute;
|
||||
import com.yandex.metrica.profile.GenderAttribute;
|
||||
|
||||
import static com.facebook.react.bridge.ReadableType.Array;
|
||||
|
||||
public class AppMetricaModule extends ReactContextBaseJavaModule {
|
||||
final static String ModuleName = "AppMetrica";
|
||||
@ -82,8 +90,125 @@ public class AppMetricaModule extends ReactContextBaseJavaModule {
|
||||
YandexMetrica.setUserProfileID(profileID);
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void reportUserProfile(ReadableMap params) {
|
||||
UserProfile.Builder userProfileBuilder = UserProfile.newBuilder();
|
||||
ReadableMapKeySetIterator iterator = params.keySetIterator();
|
||||
|
||||
while (iterator.hasNextKey()) {
|
||||
String key = iterator.nextKey();
|
||||
|
||||
switch (key) {
|
||||
// predefined attributes
|
||||
case "name":
|
||||
userProfileBuilder.apply(
|
||||
params.isNull(key)
|
||||
? Attribute.name().withValueReset()
|
||||
: Attribute.name().withValue(params.getString(key))
|
||||
);
|
||||
break;
|
||||
case "gender":
|
||||
userProfileBuilder.apply(
|
||||
params.isNull(key)
|
||||
? Attribute.gender().withValueReset()
|
||||
: Attribute.gender().withValue(
|
||||
params.getString(key).equals("female")
|
||||
? GenderAttribute.Gender.FEMALE
|
||||
: params.getString(key).equals("male")
|
||||
? GenderAttribute.Gender.MALE
|
||||
: GenderAttribute.Gender.OTHER
|
||||
)
|
||||
);
|
||||
break;
|
||||
case "age":
|
||||
userProfileBuilder.apply(
|
||||
params.isNull(key)
|
||||
? Attribute.birthDate().withValueReset()
|
||||
: Attribute.birthDate().withAge(params.getInt(key))
|
||||
);
|
||||
break;
|
||||
case "birthDate":
|
||||
if (params.isNull(key)) {
|
||||
userProfileBuilder.apply(
|
||||
Attribute.birthDate().withValueReset()
|
||||
);
|
||||
} else if (params.getType(key) == Array) {
|
||||
// an array of [ year[, month][, day] ]
|
||||
ReadableArray date = params.getArray(key);
|
||||
if (date.size() == 1) {
|
||||
userProfileBuilder.apply(
|
||||
Attribute.birthDate().withBirthDate(
|
||||
date.getInt(0)
|
||||
)
|
||||
);
|
||||
} else if (date.size() == 2) {
|
||||
userProfileBuilder.apply(
|
||||
Attribute.birthDate().withBirthDate(
|
||||
date.getInt(0),
|
||||
date.getInt(1)
|
||||
)
|
||||
);
|
||||
} else {
|
||||
userProfileBuilder.apply(
|
||||
Attribute.birthDate().withBirthDate(
|
||||
date.getInt(0),
|
||||
date.getInt(1),
|
||||
date.getInt(2)
|
||||
)
|
||||
);
|
||||
}
|
||||
} else {
|
||||
// number of milliseconds since Unix epoch
|
||||
Date date = new Date((long)params.getInt(key));
|
||||
Calendar cal = Calendar.getInstance();
|
||||
cal.setTime(date);
|
||||
userProfileBuilder.apply(
|
||||
Attribute.birthDate().withBirthDate(cal)
|
||||
);
|
||||
}
|
||||
break;
|
||||
case "notificationsEnabled":
|
||||
userProfileBuilder.apply(
|
||||
params.isNull(key)
|
||||
? Attribute.notificationsEnabled().withValueReset()
|
||||
: Attribute.notificationsEnabled().withValue(params.getBoolean(key))
|
||||
);
|
||||
break;
|
||||
// custom attributes
|
||||
default:
|
||||
// TODO: come up with a syntax solution to reset custom attributes. `null` will break type checking here
|
||||
switch (params.getType(key)) {
|
||||
case Boolean:
|
||||
userProfileBuilder.apply(
|
||||
Attribute.customBoolean(key).withValue(params.getBoolean(key))
|
||||
);
|
||||
break;
|
||||
case Number:
|
||||
userProfileBuilder.apply(
|
||||
Attribute.customNumber(key).withValue(params.getDouble(key))
|
||||
);
|
||||
break;
|
||||
case String:
|
||||
String value = params.getString(key);
|
||||
if (value.startsWith("+") || value.startsWith("-")) {
|
||||
userProfileBuilder.apply(
|
||||
Attribute.customCounter(key).withDelta(Double.parseDouble(value))
|
||||
);
|
||||
} else {
|
||||
userProfileBuilder.apply(
|
||||
Attribute.customString(key).withValue(value)
|
||||
);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
YandexMetrica.reportUserProfile(userProfileBuilder.build());
|
||||
}
|
||||
|
||||
private String convertReadableMapToJson(final ReadableMap readableMap) {
|
||||
ReadableMapKeySetIterator iterator = readableMap.keySetIterator();
|
||||
ReadableMapKeySetIterator iterator = readableMap.keySetIterator();
|
||||
JSONObject json = new JSONObject();
|
||||
|
||||
try {
|
||||
|
29
index.js
29
index.js
@ -9,6 +9,15 @@ type ActivationConfig = {
|
||||
firstActivationAsUpdate?: boolean,
|
||||
};
|
||||
|
||||
type UserProfileAttributes = {
|
||||
name?: ?string,
|
||||
gender?: 'female' | 'male' | string | void,
|
||||
age?: ?number,
|
||||
birthDate?: Date | [number] | [number, number] | [number, number, number] | void,
|
||||
notificationsEnabled?: boolean,
|
||||
[string]: string | number | boolean,
|
||||
};
|
||||
|
||||
export default {
|
||||
|
||||
/**
|
||||
@ -52,4 +61,24 @@ export default {
|
||||
setUserProfileID(userProfileId: string) {
|
||||
AppMetrica.setUserProfileID(userProfileId);
|
||||
},
|
||||
|
||||
/**
|
||||
* Sets attributes of the user profile.
|
||||
* @param {object} attributes
|
||||
*/
|
||||
reportUserProfile(attributes: UserProfileAttributes) {
|
||||
const readyAttributes = {};
|
||||
Object.keys(attributes).forEach(key => {
|
||||
if (
|
||||
key === 'birthDate' &&
|
||||
typeof attributes.birthDate === 'object' &&
|
||||
typeof attributes.birthDate.getTime === 'function'
|
||||
) {
|
||||
readyAttributes.birthDate = attributes.birthDate.getTime();
|
||||
} else {
|
||||
readyAttributes[key] = attributes[key];
|
||||
}
|
||||
});
|
||||
AppMetrica.reportUserProfile(readyAttributes);
|
||||
},
|
||||
};
|
||||
|
@ -42,4 +42,76 @@ RCT_EXPORT_METHOD(reportError:(NSString *)message) {
|
||||
RCT_EXPORT_METHOD(setUserProfileID:(NSString *)userProfileID) {
|
||||
[YMMYandexMetrica setUserProfileID:userProfileID];
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(reportUserProfile:(NSDictionary *)attributes) {
|
||||
YMMMutableUserProfile *profile = [[YMMMutableUserProfile alloc] init];
|
||||
NSMutableArray *attrsArray = [NSMutableArray array];
|
||||
for (NSString* key in attributes) {
|
||||
// predefined attributes
|
||||
if ([key isEqual: @"name"]) {
|
||||
if (attributes[key] == [NSNull null]) {
|
||||
[attrsArray addObject:[[YMMProfileAttribute name] withValueReset]];
|
||||
} else {
|
||||
[attrsArray addObject:[[YMMProfileAttribute name] withValue:[attributes[key] stringValue]]];
|
||||
}
|
||||
} else if ([key isEqual: @"gender"]) {
|
||||
if (attributes[key] == [NSNull null]) {
|
||||
[attrsArray addObject:[[YMMProfileAttribute gender] withValueReset]];
|
||||
} else {
|
||||
[attrsArray addObject:[[YMMProfileAttribute gender] withValue:[[attributes[key] stringValue] isEqual: @"female"] ? YMMGenderTypeFemale : [[attributes[key] stringValue] isEqual: @"male"] ? YMMGenderTypeMale : YMMGenderTypeOther]];
|
||||
}
|
||||
} else if ([key isEqual: @"age"]) {
|
||||
if (attributes[key] == [NSNull null]) {
|
||||
[attrsArray addObject:[[YMMProfileAttribute birthDate] withValueReset]];
|
||||
} else {
|
||||
[attrsArray addObject:[[YMMProfileAttribute birthDate] withAge:[attributes[key] intValue]]];
|
||||
}
|
||||
} else if ([key isEqual: @"birthDate"]) {
|
||||
if (attributes[key] == [NSNull null]) {
|
||||
[attrsArray addObject:[[YMMProfileAttribute birthDate] withValueReset]];
|
||||
} else if ([attributes[key] isKindOfClass:[NSArray class]]) {
|
||||
NSArray *date = [attributes[key] array];
|
||||
if ([date count] == 1) {
|
||||
[attrsArray addObject:[[YMMProfileAttribute birthDate] withYear:[[date objectAtIndex:0] intValue]]];
|
||||
} else if ([[attributes[key] array] count] == 2) {
|
||||
[attrsArray addObject:[[YMMProfileAttribute birthDate] withYear:[[date objectAtIndex:0] intValue] month:[[date objectAtIndex:1] intValue]]];
|
||||
} else if ([[attributes[key] array] count] == 3) {
|
||||
[attrsArray addObject:[[YMMProfileAttribute birthDate] withYear:[[date objectAtIndex:0] intValue] month:[[date objectAtIndex:1] intValue] day:[[date objectAtIndex:2] intValue]]];
|
||||
}
|
||||
} else {
|
||||
// number of milliseconds since Unix epoch
|
||||
NSDate *date = [attributes[key] date];
|
||||
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
|
||||
NSDateComponents *dateComponents =
|
||||
[gregorian components:(NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay) fromDate:date];
|
||||
[attrsArray addObject:[[YMMProfileAttribute birthDate] withDateComponents:dateComponents]];
|
||||
}
|
||||
} else if ([key isEqual: @"notificationsEnabled"]) {
|
||||
if (attributes[key] == [NSNull null]) {
|
||||
[attrsArray addObject:[[YMMProfileAttribute notificationsEnabled] withValueReset]];
|
||||
} else {
|
||||
[attrsArray addObject:[[YMMProfileAttribute notificationsEnabled] withValue:[attributes[key] boolValue]]];
|
||||
}
|
||||
// custom attributes
|
||||
} else {
|
||||
// TODO: come up with a syntax solution to reset custom attributes. `null` will break type checking here
|
||||
if ([attributes[key] isEqual: @YES] || [attributes[key] isEqual: @NO]) {
|
||||
[attrsArray addObject:[[YMMProfileAttribute customBool:key] withValue:[attributes[key] boolValue]]];
|
||||
} else if ([attributes[key] isKindOfClass:[NSNumber class]]) {
|
||||
[attrsArray addObject:[[YMMProfileAttribute customNumber:key] withValue:[attributes[key] doubleValue]]];
|
||||
// [NSNumber numberWithInt:[attributes[key] intValue]]
|
||||
} else if ([attributes[key] isKindOfClass:[NSString class]]) {
|
||||
if ([attributes[key] hasPrefix:@"+"] || [attributes[key] hasPrefix:@"-"]) {
|
||||
[attrsArray addObject:[[YMMProfileAttribute customCounter:key] withDelta:[attributes[key] doubleValue]]];
|
||||
} else {
|
||||
[attrsArray addObject:[[YMMProfileAttribute customString:key] withValue:attributes[key]]];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[profile applyFromArray: attrsArray];
|
||||
[YMMYandexMetrica reportUserProfile:[profile copy] onFailure:NULL];
|
||||
}
|
||||
|
||||
@end
|
||||
|
Loading…
Reference in New Issue
Block a user