diff --git a/android/build.gradle b/android/build.gradle index f2bfd7c..9fee691 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -50,7 +50,7 @@ repositories { } dependencies { - implementation 'com.yandex.android:mobmetricalib:3.8.0' + implementation 'com.yandex.android:mobmetricalib:3.18.0' implementation 'com.yandex.android:mobmetricalib-ndk-crashes:1.1.0' implementation "com.facebook.react:react-native:${safeExtGet('reactnativeVersion', '+')}" } diff --git a/android/src/main/java/com/codeard/yandexmetrica/YandexAppmetricaModule.java b/android/src/main/java/com/codeard/yandexmetrica/YandexAppmetricaModule.java index 9fd04ea..df5691d 100644 --- a/android/src/main/java/com/codeard/yandexmetrica/YandexAppmetricaModule.java +++ b/android/src/main/java/com/codeard/yandexmetrica/YandexAppmetricaModule.java @@ -4,6 +4,7 @@ import android.app.Application; import android.util.Log; +import androidx.annotation.LongDef; import androidx.annotation.NonNull; import androidx.annotation.Nullable; @@ -16,21 +17,35 @@ import com.facebook.react.bridge.ReadableType; import java.lang.Exception; +import java.util.ArrayList; +import java.util.Arrays; import java.util.Calendar; import java.util.Date; -import java.util.Arrays; import java.util.Currency; import org.json.JSONObject; import org.json.JSONArray; -import org.json.JSONException; import com.yandex.metrica.YandexMetrica; import com.yandex.metrica.YandexMetricaConfig; +import com.yandex.metrica.ecommerce.ECommerceAmount; +import com.yandex.metrica.ecommerce.ECommerceCartItem; +import com.yandex.metrica.ecommerce.ECommerceEvent; +import com.yandex.metrica.ecommerce.ECommerceOrder; +import com.yandex.metrica.ecommerce.ECommercePrice; +import com.yandex.metrica.ecommerce.ECommerceProduct; +import com.yandex.metrica.ecommerce.ECommerceReferrer; +import com.yandex.metrica.ecommerce.ECommerceScreen; import com.yandex.metrica.profile.UserProfile; import com.yandex.metrica.profile.Attribute; import com.yandex.metrica.Revenue; +import java.lang.*; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; + public class YandexAppmetricaModule extends ReactContextBaseJavaModule { private static String TAG = "YandexAppmetrica"; @@ -47,9 +62,82 @@ public String getName() { return TAG; } + public ECommerceScreen createScreen(ReadableMap params) { + ECommerceScreen screen = new ECommerceScreen().setName(params.getString("screenName")).setSearchQuery(params.getString("searchQuery")); + return screen; + } + + public ECommerceProduct createProduct(ReadableMap params) { + ECommercePrice actualPrice = new ECommercePrice(new ECommerceAmount(Integer.parseInt(params.getString("price")), params.getString("currency"))); + ECommerceProduct product = new ECommerceProduct(params.getString("sku")).setActualPrice(actualPrice).setName(params.getString("name")); + return product; + } + + public ECommerceCartItem createCartItem(ReadableMap params) { + ECommerceScreen screen = this.createScreen(params); + ECommerceProduct product = this.createProduct(params); + ECommercePrice actualPrice = new ECommercePrice(new ECommerceAmount(Integer.parseInt(params.getString("price")), params.getString("currency"))); + ECommerceReferrer referrer = new ECommerceReferrer().setScreen(screen); + ECommerceCartItem cartItem = new ECommerceCartItem(product, actualPrice, Integer.parseInt(params.getString("quantity"))).setReferrer(referrer); + return cartItem; + } + + @ReactMethod + public void showScreen(ReadableMap params) { + ECommerceScreen screen = this.createScreen(params); + ECommerceEvent showScreenEvent = ECommerceEvent.showScreenEvent(screen); + YandexMetrica.reportECommerce(showScreenEvent); + } + + @ReactMethod + public void showProductCard(ReadableMap params) { + ECommerceScreen screen = this.createScreen(params); + ECommerceProduct product = this.createProduct(params); + ECommerceEvent showProductCardEvent = ECommerceEvent.showProductCardEvent(product, screen); + YandexMetrica.reportECommerce(showProductCardEvent); + } + + @ReactMethod + public void addToCart(ReadableMap params) { + ECommerceCartItem cartItem = this.createCartItem(params); + ECommerceEvent addCartItemEvent = ECommerceEvent.addCartItemEvent(cartItem); + YandexMetrica.reportECommerce(addCartItemEvent); + } + + @ReactMethod + public void removeFromCart(ReadableMap params) { + ECommerceCartItem cartItem = this.createCartItem(params); + ECommerceEvent removeCartItemEvent = ECommerceEvent.removeCartItemEvent(cartItem); + YandexMetrica.reportECommerce(removeCartItemEvent); + } + + @ReactMethod + public void beginCheckout(ReadableArray products, String identifier) { + ArrayList cartItems = new ArrayList<>(); + for (int i = 0; i < products.size(); i++) { + ReadableMap productData = products.getMap(i); + cartItems.add(this.createCartItem(productData)); + } + ECommerceOrder order = new ECommerceOrder(identifier, cartItems); + ECommerceEvent beginCheckoutEvent = ECommerceEvent.beginCheckoutEvent(order); + YandexMetrica.reportECommerce(beginCheckoutEvent); + } + + @ReactMethod + public void finishCheckout(ReadableArray products, String identifier) { + ArrayList cartItems = new ArrayList<>(); + for (int i = 0; i < products.size(); i++) { + ReadableMap productData = products.getMap(i); + cartItems.add(this.createCartItem(productData)); + } + ECommerceOrder order = new ECommerceOrder(identifier, cartItems); + ECommerceEvent purchaseEvent = ECommerceEvent.purchaseEvent(order); + YandexMetrica.reportECommerce(purchaseEvent); + } + @ReactMethod public void activateWithApiKey(String apiKey) { - YandexMetricaConfig.Builder configBuilder = YandexMetricaConfig.newConfigBuilder(apiKey); + YandexMetricaConfig.Builder configBuilder = YandexMetricaConfig.newConfigBuilder(apiKey).withLogs(); YandexMetrica.activate(getReactApplicationContext().getApplicationContext(), configBuilder.build()); Activity activity = getCurrentActivity(); if (activity != null) { @@ -60,7 +148,7 @@ public void activateWithApiKey(String apiKey) { @ReactMethod public void activateWithConfig(ReadableMap params) { - YandexMetricaConfig.Builder configBuilder = YandexMetricaConfig.newConfigBuilder(params.getString("apiKey")); + YandexMetricaConfig.Builder configBuilder = YandexMetricaConfig.newConfigBuilder(params.getString("apiKey")).withLogs(); if (params.hasKey("sessionTimeout")) { configBuilder.withSessionTimeout(params.getInt("sessionTimeout")); } @@ -76,16 +164,13 @@ public void activateWithConfig(ReadableMap params) { } @ReactMethod - public void reportEvent(String message, @Nullable ReadableMap params) { - try { - if (params != null) { - YandexMetrica.reportEvent(message, convertMapToJson(params).toString()); - } else { - YandexMetrica.reportEvent(message); - } - } catch (Exception e) { - Log.e(TAG, "Unable to report Yandex Mobile Metrica event: " + e); - } + public void reportEvent(String message) { + YandexMetrica.reportEvent(message); + } + + @ReactMethod + public void reportEventWithParams(String message, @Nullable ReadableMap params) { + YandexMetrica.reportEvent(message, convertMapToJson(params).toString()); } @ReactMethod diff --git a/ios/YandexAppmetrica.m b/ios/YandexAppmetrica.m index 59e88e4..e62ffd0 100644 --- a/ios/YandexAppmetrica.m +++ b/ios/YandexAppmetrica.m @@ -12,11 +12,14 @@ @implementation YandexAppmetrica { RCT_EXPORT_METHOD(activateWithApiKey:(NSString *)apiKey) { YMMYandexMetricaConfiguration *configuration = [[YMMYandexMetricaConfiguration alloc] initWithApiKey:apiKey]; + configuration.logs = YES; [YMMYandexMetrica activateWithConfiguration:configuration]; + RCTLogInfo(@"activateWithApiKey - %@", apiKey); } RCT_EXPORT_METHOD(activateWithConfig:(NSDictionary *)config) { YMMYandexMetricaConfiguration *configuration = [[YMMYandexMetricaConfiguration alloc] initWithApiKey:config[@"apiKey"]]; + configuration.logs = YES; if (config[@"sessionTimeout"] != (id)nil) { [configuration setSessionTimeout:[config[@"sessionTimeout"] intValue]]; } @@ -26,14 +29,15 @@ @implementation YandexAppmetrica { [YMMYandexMetrica activateWithConfiguration:configuration]; } -RCT_EXPORT_METHOD(reportEvent:(NSString *)message) +RCT_EXPORT_METHOD(reportEventWithParams:(NSString *)message params:(nullable NSDictionary *) params) { - [YMMYandexMetrica reportEvent:message onFailure:NULL]; + RCTLogInfo(@"reportEvent message - %@", message); + [YMMYandexMetrica reportEvent:message parameters:params onFailure:NULL]; } -RCT_EXPORT_METHOD(reportEvent:(NSString *)message params:(nullable NSDictionary *) params) +RCT_EXPORT_METHOD(reportEvent:(NSString *)message) { - [YMMYandexMetrica reportEvent:message parameters:params onFailure:NULL]; + [YMMYandexMetrica reportEvent:message onFailure:NULL]; } RCT_EXPORT_METHOD(reportError:(NSString *)message exception:(nullable NSString *) exceptionText) { @@ -51,6 +55,95 @@ @implementation YandexAppmetrica { }]; } +- (YMMECommerceScreen *)createScreen:(NSDictionary *)screen { + YMMECommerceScreen *screenObj = [[YMMECommerceScreen alloc] initWithName:screen[@"screenName"] categoryComponents:@[] searchQuery:screen[@"searchQuery"] payload:@{}]; + return screenObj; +} + +- (YMMECommerceProduct *)createProduct:(NSDictionary *)product { + YMMECommerceAmount *actualFiat = [[YMMECommerceAmount alloc] initWithUnit:product[@"currency"] value:[NSDecimalNumber decimalNumberWithString:product[@"price"]]]; + YMMECommercePrice *actualPrice = [[YMMECommercePrice alloc] initWithFiat:actualFiat internalComponents:@[]]; + YMMECommerceProduct *productObj = [[YMMECommerceProduct alloc] initWithSKU:product[@"sku"] name:product[@"name"] categoryComponents:@[] payload:@{} actualPrice:actualPrice originalPrice:actualPrice promoCodes:@[]]; + + return productObj; +} + +- (YMMECommercePrice *)createPrice:(NSDictionary *)product { + YMMECommerceAmount *priceObj = [[YMMECommerceAmount alloc] initWithUnit:product[@"currency"] value:[NSDecimalNumber decimalNumberWithString:product[@"price"]]]; + YMMECommercePrice *actualPrice = [[YMMECommercePrice alloc] initWithFiat:priceObj internalComponents:@[]]; + + return actualPrice; +} + +- (YMMECommerceCartItem *)createCartItem:(NSDictionary *)product { + YMMECommerceScreen *screen = [self createScreen:@{}]; + + YMMECommerceProduct *productObj = [self createProduct:product]; + + YMMECommerceReferrer *referrer = [[YMMECommerceReferrer alloc] initWithType:@"" identifier:@"" screen:screen]; + + NSDecimalNumber *quantity = [NSDecimalNumber decimalNumberWithString:product[@"quantity"]]; + + YMMECommercePrice *actualPrice = [self createPrice:product]; + + YMMECommerceCartItem *cartItem = [[YMMECommerceCartItem alloc] initWithProduct:productObj quantity:quantity revenue:actualPrice referrer:referrer]; + + return cartItem; +} + +// Используйте его, чтобы сообщить об открытии какой-либо страницы, например: списка товаров, поиска, главной страницы. +RCT_EXPORT_METHOD(showScreen:(NSDictionary *)screen) { + YMMECommerceScreen *screenObj = [self createScreen:screen]; + + [YMMYandexMetrica reportECommerce:[YMMECommerce showScreenEventWithScreen:screenObj] onFailure:nil]; +} + +// Используйте его, чтобы сообщить о просмотре карточки товара среди других в списке. +RCT_EXPORT_METHOD(showProductCard:(NSDictionary *)product ) { + YMMECommerceScreen *screen = [self createScreen:@{}]; + YMMECommerceProduct *productObj = [self createProduct:product]; + + [YMMYandexMetrica reportECommerce:[YMMECommerce showProductCardEventWithProduct:productObj screen:screen] onFailure:nil]; +} + +RCT_EXPORT_METHOD(addToCart:(NSDictionary *)product) { + YMMECommerceCartItem *cartItem = [self createCartItem:product]; + + [YMMYandexMetrica reportECommerce:[YMMECommerce addCartItemEventWithItem:cartItem] onFailure:nil]; +} + +RCT_EXPORT_METHOD(removeFromCart:(NSDictionary *)product) { + YMMECommerceCartItem *cartItem = [self createCartItem:product]; + + [YMMYandexMetrica reportECommerce:[YMMECommerce removeCartItemEventWithItem:cartItem] onFailure:nil]; +} + +RCT_EXPORT_METHOD(beginCheckout:(NSArray *)products identifier:(NSString *)identifier) { + NSMutableArray *cartItems = [[NSMutableArray alloc] init]; + for(int i=0; i< products.count; i++){ + [cartItems addObject:[self createCartItem:products[i]]]; + } + + YMMECommerceOrder *order = [[YMMECommerceOrder alloc] initWithIdentifier:identifier + cartItems:cartItems + payload:@{}]; + + [YMMYandexMetrica reportECommerce:[YMMECommerce beginCheckoutEventWithOrder:order] onFailure:nil]; +} + + +RCT_EXPORT_METHOD(finishCheckout:(NSArray *)products identifier:(NSString *)identifier) { + NSMutableArray *cartItems = [[NSMutableArray alloc] init]; + for(int i=0; i< products.count; i++){ + [cartItems addObject:[self createCartItem:products[i]]]; + } + YMMECommerceOrder *order = [[YMMECommerceOrder alloc] initWithIdentifier:identifier + cartItems:cartItems + payload:@{}]; + + [YMMYandexMetrica reportECommerce:[YMMECommerce purchaseEventWithOrder:order] onFailure:nil]; +} + RCT_EXPORT_METHOD(setUserProfileID:(NSString *)userProfileID) { [YMMYandexMetrica setUserProfileID:userProfileID]; } diff --git a/react-native-appmetrica-yandex.podspec b/react-native-appmetrica-yandex.podspec index d70ff2b..e55ea9c 100644 --- a/react-native-appmetrica-yandex.podspec +++ b/react-native-appmetrica-yandex.podspec @@ -20,7 +20,6 @@ Pod::Spec.new do |s| s.requires_arc = true s.dependency "React" - s.dependency "YandexMobileMetrica", "3.8.2" + s.dependency "YandexMobileMetrica", "3.14.0" end -