diff --git a/android/src/main/java/com/revenuecat/purchases/react/RNPurchasesModule.java b/android/src/main/java/com/revenuecat/purchases/react/RNPurchasesModule.java index d458d8271..0d24977d0 100644 --- a/android/src/main/java/com/revenuecat/purchases/react/RNPurchasesModule.java +++ b/android/src/main/java/com/revenuecat/purchases/react/RNPurchasesModule.java @@ -666,8 +666,11 @@ public void generateRewardVerificationToken(String impressionId, final Promise p } @ReactMethod - public void pollRewardVerification(String clientTransactionId, final Promise promise) { - CommonKt.pollRewardVerification(clientTransactionId, getOnResult(promise)); + public void pollRewardVerification(String clientTransactionId, + @Nullable ReadableMap trackingMetadata, + final Promise promise) { + Map mapTrackingMetadata = trackingMetadata != null ? trackingMetadata.toHashMap() : null; + CommonKt.pollRewardVerification(clientTransactionId, getOnResult(promise), mapTrackingMetadata); } // endregion diff --git a/apitesters/rewardVerification.ts b/apitesters/rewardVerification.ts index 7a865ef7e..a5a4dd5aa 100644 --- a/apitesters/rewardVerification.ts +++ b/apitesters/rewardVerification.ts @@ -1,11 +1,14 @@ import Purchases, { RewardVerificationToken, RewardVerificationResult, + RewardedAdTrackingMetadata, VerifiedReward, VerifiedVirtualCurrencyReward, VerifiedEntitlementReward, VerifiedNoReward, VerifiedUnsupportedReward, + AdMediatorName, + AdFormat, } from "../src"; async function checkGenerateRewardVerificationToken() { @@ -24,6 +27,22 @@ async function checkPollRewardVerification() { const _moreRewards: VerifiedReward[] = result.moreRewards; } +async function checkPollRewardVerificationWithTrackingMetadata() { + const trackingMetadata: RewardedAdTrackingMetadata = { + mediatorName: AdMediatorName.adMob, + adFormat: AdFormat.rewarded, + adUnitId: "unit-1", + impressionId: "imp-1", + networkName: "AdNetwork", + placement: "home", + }; + const result: RewardVerificationResult = + await Purchases.pollRewardVerification( + "client-transaction-id", + trackingMetadata + ); +} + function checkVerifiedRewardTypes(reward: VerifiedReward) { switch (reward.type) { case "virtual_currency": { diff --git a/ios/RNPurchases.m b/ios/RNPurchases.m index 66e0567dd..5d8276736 100644 --- a/ios/RNPurchases.m +++ b/ios/RNPurchases.m @@ -714,9 +714,11 @@ static void logUnavailablePresentCodeRedemptionSheet() { } RCT_EXPORT_METHOD(pollRewardVerification:(NSString *)clientTransactionId - resolve:(RCTPromiseResolveBlock)resolve - reject:(RCTPromiseRejectBlock)reject) { + trackingMetadata:(nullable NSDictionary *)trackingMetadata + resolve:(RCTPromiseResolveBlock)resolve + reject:(RCTPromiseRejectBlock)reject) { [RCCommonFunctionality pollRewardVerificationWithClientTransactionId:clientTransactionId + trackingMetadata:trackingMetadata.mappingNSNullToNil completion:[self getResponseCompletionBlockWithResolve:resolve reject:reject]]; } diff --git a/src/browser/nativeModule.ts b/src/browser/nativeModule.ts index c865ae00b..2649447f5 100644 --- a/src/browser/nativeModule.ts +++ b/src/browser/nativeModule.ts @@ -7,6 +7,7 @@ import { validateAndTransform, isCustomerInfo, isPurchasesOfferings, isPurchases import { isExpoGo, isRorkSandbox } from '../utils/environment'; import { ensurePurchasesConfigured, methodNotSupportedOnWeb } from './utils'; import { purchaseSimulatedPackage } from './simulatedstore/purchaseSimulatedPackageHelper'; +import type { RewardedAdTrackingMetadata } from '../purchases'; const packageVersion = '9.1.0'; @@ -366,7 +367,7 @@ export const browserNativeModuleRNPurchases = { generateRewardVerificationToken: async (_impressionId: string) => { methodNotSupportedOnWeb('generateRewardVerificationToken'); }, - pollRewardVerification: async (_clientTransactionId: string) => { + pollRewardVerification: async (_clientTransactionId: string, _trackingMetadata?: RewardedAdTrackingMetadata) => { methodNotSupportedOnWeb('pollRewardVerification'); }, }; diff --git a/src/purchases.ts b/src/purchases.ts index 601492546..37f24262b 100644 --- a/src/purchases.ts +++ b/src/purchases.ts @@ -340,6 +340,20 @@ export interface RewardVerificationResult { failed: boolean; } +/** + * Ad metadata for a rewarded ad, passed to {@link Purchases.pollRewardVerification} + * to have the SDK automatically track reward-verification events for it. + * @beta + */ +export interface RewardedAdTrackingMetadata { + mediatorName: AdMediatorName; + adFormat: AdFormat; + adUnitId: string; + impressionId: string; + networkName?: string | null; + placement?: string | null; +} + let debugEventListeners: DebugEventListener[] = []; eventEmitter?.addListener( @@ -2167,14 +2181,21 @@ export default class Purchases { * * @param clientTransactionId - The `clientTransactionId` from * {@link Purchases.generateRewardVerificationToken}. + * @param trackingMetadata - Pass to have the SDK automatically track + * reward-verification events for the ad it belongs to; omit to poll + * without tracking. * @returns {Promise} promise with the verification result. * @beta */ public static async pollRewardVerification( - clientTransactionId: string + clientTransactionId: string, + trackingMetadata?: RewardedAdTrackingMetadata ): Promise { await throwIfNotConfigured(); - return RNPurchases.pollRewardVerification(clientTransactionId); + return RNPurchases.pollRewardVerification( + clientTransactionId, + trackingMetadata + ); } private static async throwIfAndroidPlatform() {