diff --git a/AppsFlyerSDK/Source/AppsFlyerSDK/AppsFlyer_UPL_Android.xml b/AppsFlyerSDK/Source/AppsFlyerSDK/AppsFlyer_UPL_Android.xml
index a1a2097..648e621 100644
--- a/AppsFlyerSDK/Source/AppsFlyerSDK/AppsFlyer_UPL_Android.xml
+++ b/AppsFlyerSDK/Source/AppsFlyerSDK/AppsFlyer_UPL_Android.xml
@@ -41,6 +41,14 @@
import com.appsflyer.internal.platform_extension.PluginInfo;
import java.util.HashMap;
import java.util.Map;
+
+ import com.appsflyer.AFAdRevenueData;
+ import com.appsflyer.MediationNetwork;
+ import com.appsflyer.AppsFlyerLib;
+
+ import java.util.Currency;
+
+ import android.util.Log;
@@ -92,6 +100,27 @@
AppsFlyerLib.getInstance().disableAppSetId();
}
+ public void afLogAdRevenue(
+ String monetizationNetwork,
+ int mediationNetwork,
+ double revenue,
+ String currency,
+ Map customData)
+ {
+ AFAdRevenueData adRevenueData = new AFAdRevenueData(monetizationNetwork, getAFMediationNetwork(mediationNetwork), currency, revenue);
+
+ Map additionalParameters = new HashMap<>();
+
+ if(customData.containsKey("Country")) additionalParameters.put(AdRevenueScheme.COUNTRY, customData.get("Country"));
+ if(customData.containsKey("UnitID")) additionalParameters.put(AdRevenueScheme.AD_UNIT, customData.get("UnitID"));
+ if(customData.containsKey("AdType")) additionalParameters.put(AdRevenueScheme.AD_TYPE, customData.get("AdType"));
+ if(customData.containsKey("Placement")) additionalParameters.put(AdRevenueScheme.PLACEMENT, customData.get("Placement"));
+
+ AppsFlyerLib.getInstance().logAdRevenue(adRevenueData, additionalParameters);
+
+ Log.debug("AppsflyerLog Track ad revenue");
+ }
+
// Deprecated
public void afSetConsentData(boolean isGDPR, boolean hasConsentForDataUsage, boolean hasConsentForAdsPersonalization) {
AppsFlyerConsent consent;
@@ -117,6 +146,25 @@
AppsFlyerLib.getInstance().setConsentData(consent);
}
+
+ public MediationNetwork getAFMediationNetwork(int network){
+ switch (network) {
+ case 0: return MediationNetwork.IRONSOURCE;
+ case 1: return MediationNetwork.APPLOVIN_MAX;
+ case 2: return MediationNetwork.GOOGLE_ADMOB;
+ case 3: return MediationNetwork.FYBER;
+ case 4: return MediationNetwork.APPODEAL;
+ case 5: return MediationNetwork.ADMOST;
+ case 6: return MediationNetwork.TOPON;
+ case 7: return MediationNetwork.TRADPLUS;
+ case 8: return MediationNetwork.YANDEX;
+ case 9: return MediationNetwork.CHARTBOOST;
+ case 10: return MediationNetwork.UNITY;
+ case 11: return MediationNetwork.CUSTOM_MEDIATION;
+ case 12: return MediationNetwork.DIRECT_MONETIZATION_NETWORK;
+ default: return MediationNetwork.CUSTOM_MEDIATION;
+ }
+ }
diff --git a/AppsFlyerSDK/Source/AppsFlyerSDK/Private/AppsFlyerSDKBlueprint.cpp b/AppsFlyerSDK/Source/AppsFlyerSDK/Private/AppsFlyerSDKBlueprint.cpp
index c0cb119..ca211e6 100755
--- a/AppsFlyerSDK/Source/AppsFlyerSDK/Private/AppsFlyerSDKBlueprint.cpp
+++ b/AppsFlyerSDK/Source/AppsFlyerSDK/Private/AppsFlyerSDKBlueprint.cpp
@@ -200,6 +200,26 @@ static void onAppOpenAttribution(NSDictionary *attributionData) {
static void onAppOpenAttributionFailure(NSString *error) {
NSLog(@"%@", error);
}
+
+static AppsFlyerAdRevenueMediationNetworkType mediationNetworkIOSTypeFromEnum(EAFMediationNetwork network) {
+ switch (network)
+ {
+ case EAFMediationNetwork::Ironsource: return AppsFlyerAdRevenueMediationNetworkTypeIronSource;
+ case EAFMediationNetwork::Applovinmax: return AppsFlyerAdRevenueMediationNetworkTypeApplovinMax;
+ case EAFMediationNetwork::Googleadmob: return AppsFlyerAdRevenueMediationNetworkTypeGoogleAdMob;
+ case EAFMediationNetwork::Fyber: return AppsFlyerAdRevenueMediationNetworkTypeFyber;
+ case EAFMediationNetwork::Appodeal: return AppsFlyerAdRevenueMediationNetworkTypeAppodeal;
+ case EAFMediationNetwork::Admost: return AppsFlyerAdRevenueMediationNetworkTypeAdmost;
+ case EAFMediationNetwork::Topon: return AppsFlyerAdRevenueMediationNetworkTypeTopon;
+ case EAFMediationNetwork::Tradplus: return AppsFlyerAdRevenueMediationNetworkTypeTradplus;
+ case EAFMediationNetwork::Yandex: return AppsFlyerAdRevenueMediationNetworkTypeYandex;
+ case EAFMediationNetwork::Chartboost: return AppsFlyerAdRevenueMediationNetworkTypeChartBoost;
+ case EAFMediationNetwork::Unity: return AppsFlyerAdRevenueMediationNetworkTypeUnity;
+ case EAFMediationNetwork::CustomMediation: return AppsFlyerAdRevenueMediationNetworkTypeCustom;
+ case EAFMediationNetwork::DirectMonetizationNetwork: return AppsFlyerAdRevenueMediationNetworkTypeDirectMonetization;
+ default: return AppsFlyerAdRevenueMediationNetworkTypeCustom;
+ }
+}
#endif
UAppsFlyerSDKBlueprint::UAppsFlyerSDKBlueprint(const FObjectInitializer &ObjectInitializer) : Super(ObjectInitializer) {}
@@ -649,6 +669,55 @@ void UAppsFlyerSDKBlueprint::SetConsentDataTOptional(
);
}
+void UAppsFlyerSDKBlueprint::logAdRevenue(FString monetizationNetwork, EAFMediationNetwork mediationNetwork, float revenue, FString currency, TMap extraData)
+{
+#if PLATFORM_ANDROID
+ JNIEnv* env = FAndroidApplication::GetJavaEnv();
+ jmethodID method = FJavaWrapper::FindMethod(env,
+ FJavaWrapper::GameActivityClassID,
+ "afLogAdRevenue",
+ "(Ljava/lang/String;IDLjava/lang/String;Ljava/util/Map;)V", false);
+
+ jclass mapClass = env->FindClass("java/util/HashMap");
+ jmethodID mapConstructor = env->GetMethodID(mapClass, "", "()V");
+ jobject map = env->NewObject(mapClass, mapConstructor);
+ jmethodID putMethod = env->GetMethodID(mapClass, "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
+ for (const TPair& pair : extraData) {
+ env->CallObjectMethod(map, putMethod, env->NewStringUTF(TCHAR_TO_UTF8(*pair.Key)), env->NewStringUTF(TCHAR_TO_UTF8(*pair.Value)));
+ }
+
+ jstring jNetworkName = env->NewStringUTF(TCHAR_TO_UTF8(*monetizationNetwork));
+ jint jMediation = static_cast(mediationNetwork);
+ jstring jCurrency = env->NewStringUTF(TCHAR_TO_UTF8(*currency));
+
+ FJavaWrapper::CallVoidMethod(env, FJavaWrapper::GameActivityThis, method, jNetworkName, jMediation, revenue, jCurrency, map);
+
+ env->DeleteLocalRef(jNetworkName);
+ env->DeleteLocalRef(jCurrency);
+#elif PLATFORM_IOS
+ dispatch_async(dispatch_get_main_queue(), ^ {
+ AFAdRevenueData* AdRevenue = [[AFAdRevenueData alloc]
+ initWithMonetizationNetwork: monetizationNetwork.GetNSString()
+ mediationNetwork: mediationNetworkIOSTypeFromEnum(mediationNetwork)
+ currencyIso4217Code: currency.GetNSString()
+ eventRevenue: [NSNumber numberWithFloat: revenue]
+ ];
+
+ NSMutableDictionary* additionalParameters = [[NSMutableDictionary alloc] init];
+ if (extraData.Contains("Country")) [additionalParameters setValue:extraData["Country"].GetNSString() forKey:kAppsFlyerAdRevenueCountry];
+ if (extraData.Contains("AdType")) [additionalParameters setValue:extraData["AdType"].GetNSString() forKey:kAppsFlyerAdRevenueAdType];
+ if (extraData.Contains("UnitID")) [additionalParameters setValue:extraData["UnitID"].GetNSString() forKey:kAppsFlyerAdRevenueAdUnit];
+ if (extraData.Contains("Placement")) [additionalParameters setValue:extraData["Placement"].GetNSString() forKey:kAppsFlyerAdRevenuePlacement];
+
+ [[AppsFlyerLib shared] logAdRevenue:AdRevenue additionalParameters:additionalParameters];
+ });
+#else
+ return;
+#endif
+
+ UE_LOG(LogAppsFlyerSDKBlueprint, Log, TEXT("Log ad revenue"));
+}
+
void UAppsFlyerSDKBlueprint::ValidateAndLogInAppPurchase(
const FAFSDKPurchaseDetails& PurchaseDetails,
const TMap& PurchaseAdditionalDetails)
diff --git a/AppsFlyerSDK/Source/AppsFlyerSDK/Public/AppsFlyerSDKBlueprint.h b/AppsFlyerSDK/Source/AppsFlyerSDK/Public/AppsFlyerSDKBlueprint.h
index e93b004..83479de 100755
--- a/AppsFlyerSDK/Source/AppsFlyerSDK/Public/AppsFlyerSDKBlueprint.h
+++ b/AppsFlyerSDK/Source/AppsFlyerSDK/Public/AppsFlyerSDKBlueprint.h
@@ -30,6 +30,24 @@ enum class EAFValidateAndLogStatus : uint8
Error UMETA(DisplayName = "Error")
};
+UENUM(BlueprintType)
+enum class EAFMediationNetwork : uint8
+{
+ Ironsource UMETA(DisplayName = "IronSource"),
+ Applovinmax UMETA(DisplayName = "ApplovinMax"),
+ Googleadmob UMETA(DisplayName = "GoogleAdmob"),
+ Fyber UMETA(DisplayName = "Fyber"),
+ Appodeal UMETA(DisplayName = "Appodeal"),
+ Admost UMETA(DisplayName = "Admost"),
+ Topon UMETA(DisplayName = "Topon"),
+ Tradplus UMETA(DisplayName = "TradPlus"),
+ Yandex UMETA(DisplayName = "Yandex"),
+ Chartboost UMETA(DisplayName = "Chartboost"),
+ Unity UMETA(DisplayName = "Unity"),
+ CustomMediation UMETA(DisplayName = "Custom Mediation"),
+ DirectMonetizationNetwork UMETA(DisplayName = "Direct Monetization Network")
+};
+
USTRUCT(BlueprintType)
struct FAFSDKPurchaseDetails
{
@@ -137,6 +155,17 @@ class APPSFLYERSDK_API UAppsFlyerSDKBlueprint : public UBlueprintFunctionLibrary
TOptional HasConsentForAdStorage
);
+ /*!
+ * Log revenue from ads
+ * @param monetizationNetwork - Monetization network the ad was shown by, such as AdMob, UnityAds, Facebook e.t.c.
+ * @param mediationNetwork - Mediation network.
+ * @param revenue - Ad revenue (in millions)
+ * @param currency - Currency code
+ * @param extraData - Optional extra info for ad revenue. Can have "Country", "UnitID", "AdType" and "Placement" keys.
+ */
+ UFUNCTION(BlueprintCallable, Category = AppsFlyerSDK, DisplayName = "AppsFlyerSDK log ad revenue")
+ static void logAdRevenue(FString monetizationNetwork, EAFMediationNetwork mediationNetwork, float revenue, FString currency, TMap extraData);
+
/*!
* Validates and logs an in-app purchase using the updated VAL V2 flow.
* This method should be called after a successful transaction.