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
|
```js
|
||||||
import AppMetrica from 'react-native-appmetrica';
|
import AppMetrica from 'react-native-appmetrica';
|
||||||
|
|
||||||
// Starts the statistics collection process.
|
// Start the statistics collection process.
|
||||||
AppMetrica.activateWithApiKey('...KEY...');
|
AppMetrica.activateWithApiKey('...KEY...');
|
||||||
// OR
|
// OR
|
||||||
AppMetrica.activateWithConfig({
|
AppMetrica.activateWithConfig({
|
||||||
@ -40,10 +40,40 @@ AppMetrica.activateWithConfig({
|
|||||||
firstActivationAsUpdate: true,
|
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');
|
||||||
AppMetrica.reportEvent('My event', { foo: 'bar' });
|
AppMetrica.reportEvent('My event', { foo: 'bar' });
|
||||||
|
|
||||||
// Send a custom error event.
|
// Send a custom error event.
|
||||||
AppMetrica.reportError('My error');
|
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.ReactApplicationContext;
|
||||||
import com.facebook.react.bridge.ReactContextBaseJavaModule;
|
import com.facebook.react.bridge.ReactContextBaseJavaModule;
|
||||||
import com.facebook.react.bridge.ReactMethod;
|
import com.facebook.react.bridge.ReactMethod;
|
||||||
|
import com.facebook.react.bridge.ReadableArray;
|
||||||
import com.facebook.react.bridge.ReadableMap;
|
import com.facebook.react.bridge.ReadableMap;
|
||||||
import com.facebook.react.bridge.ReadableMapKeySetIterator;
|
import com.facebook.react.bridge.ReadableMapKeySetIterator;
|
||||||
|
|
||||||
import java.lang.Exception;
|
import java.lang.Exception;
|
||||||
|
import java.util.Calendar;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
|
|
||||||
import com.yandex.metrica.YandexMetrica;
|
import com.yandex.metrica.YandexMetrica;
|
||||||
import com.yandex.metrica.YandexMetricaConfig;
|
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 {
|
public class AppMetricaModule extends ReactContextBaseJavaModule {
|
||||||
final static String ModuleName = "AppMetrica";
|
final static String ModuleName = "AppMetrica";
|
||||||
@ -82,6 +90,123 @@ public class AppMetricaModule extends ReactContextBaseJavaModule {
|
|||||||
YandexMetrica.setUserProfileID(profileID);
|
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) {
|
private String convertReadableMapToJson(final ReadableMap readableMap) {
|
||||||
ReadableMapKeySetIterator iterator = readableMap.keySetIterator();
|
ReadableMapKeySetIterator iterator = readableMap.keySetIterator();
|
||||||
JSONObject json = new JSONObject();
|
JSONObject json = new JSONObject();
|
||||||
|
29
index.js
29
index.js
@ -9,6 +9,15 @@ type ActivationConfig = {
|
|||||||
firstActivationAsUpdate?: boolean,
|
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 {
|
export default {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -52,4 +61,24 @@ export default {
|
|||||||
setUserProfileID(userProfileId: string) {
|
setUserProfileID(userProfileId: string) {
|
||||||
AppMetrica.setUserProfileID(userProfileId);
|
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) {
|
RCT_EXPORT_METHOD(setUserProfileID:(NSString *)userProfileID) {
|
||||||
[YMMYandexMetrica setUserProfileID: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
|
@end
|
||||||
|
Loading…
Reference in New Issue
Block a user