UNPKG

@braze/react-native-sdk

Version:
1,095 lines (1,004 loc) 40.7 kB
import { DeviceEventEmitter, NativeEventEmitter, Platform } from 'react-native'; import { Button } from './models/button'; import { InAppMessage } from './models/in-app-message'; import { CardCategory, NotificationSubscriptionTypes, Genders, TrackingProperty, ContentCardTypes, Events, ClickAction, DismissType, MessageType } from './models/enums'; import BannerView from './ui/braze-banner-view'; import { callFunctionWithCallback, parseNestedProperties } from './helpers'; export class Braze { static BrazeButton = Button; static BrazeInAppMessage = InAppMessage; static BrazeBannerView = BannerView; static CardCategory = CardCategory; static NotificationSubscriptionTypes = NotificationSubscriptionTypes; static Genders = Genders; static TrackingProperty = TrackingProperty; static ContentCardTypes = ContentCardTypes; static Events = Events; static ClickAction = ClickAction; static DismissType = DismissType; static MessageType = MessageType; static bridge = require('./specs/NativeBrazeReactModule').default; static eventEmitter = Platform.select({ ios: new NativeEventEmitter(this.bridge), android: DeviceEventEmitter }); /** * @deprecated This method is deprecated in favor of `getInitialPushPayload`. * * To get the initial URL, call `getInitialPushPayload` and get the `url` key from the payload object. */ static getInitialURL(callback) { if (Platform.OS === 'ios') { this.bridge.getInitialURL((err, res) => { if (err) { console.log(err); callback(null); } else { callback(res); } }); } else { // BrazeReactBridge.getInitialUrl not implemented on Android callback(null); } } /** * When launching an iOS application that has previously been force closed, React Native's Linking API doesn't * support handling push notifications and deep links in the payload. This is due to a race condition on startup between * the native call to RCTLinkingManager and React's loading of its JavaScript. This function provides a workaround: * If an application is launched from a push notification click, we return the full push payload. * @param {function(string)} callback - A callback that retuns the push notification as an Object. If there is no push payload, * returns null. */ static getInitialPushPayload(callback) { if (Platform.OS === 'ios') { this.bridge.getInitialPushPayload((err, res) => { if (err) { console.log(err); callback(null); } else { callback(res); } }); } else { // BrazeReactBridge.getInitialPushPayload not implemented on Android callback(null); } } /** * @deprecated This method is deprecated in favor of `getDeviceId`. */ static getInstallTrackingId(callback) { callFunctionWithCallback( this.bridge.getDeviceId, [], callback ); } /** * Returns a unique ID stored on the device. * * On Android, a randomly generated, app specific ID that is stored on the device. A new ID will be generated if the user * clears the data for the app or removes/re-installs the app. The ID will persist across Braze.changeUser calls. * * On iOS, this ID is generated from the IDFV. This behavior will be updated in the next major version. * @param {function(error, result)} callback - A callback that receives the function call result. */ static getDeviceId(callback) { callFunctionWithCallback( this.bridge.getDeviceId, [], callback ); } /** * When a user first uses Braze on a device they are considered "anonymous". Use this method to identify a user * with a unique ID, which enables the following: * * - If the same user is identified on another device, their user profile, usage history and event history will * be shared across devices. * - If your app is used on the same device by multiple people, you can assign each of them a unique identifier * to track them separately. Only the most recent user on a particular browser will receive push * notifications and in-app messages. * * When you request a user switch (which is any call to changeUser where the new user ID is not the same as the * existing user ID), the current session for the previous user (anonymous or not) is automatically ended and * a new session is started. Similarly, following a call to changeUser, any events which fire are guaranteed to * be for the new user -- if an in-flight server request completes for the old user after the user switch no * events will fire, so you do not need to worry about filtering out events from Braze for old users. * * Additionally, if you identify a user which has never been identified on another device, the entire history of * that user as an "anonymous" user on this device will be preserved and associated with the newly identified * user. However, if you identify a user which *has* been identified in another app, any history which was * already flushed to the server for the anonymous user on this device will become orphaned and will not be * associated with any future users. These orphaned users are not considered in your user counts and will not * be messaged. * * Note: Once you identify a user, you cannot revert to the "anonymous" user. The transition from anonymous to * identified tracking is only allowed once because the initial anonymous user receives special treatment to * allow for preservation of their history. As a result, we recommend against changing the user ID just because * your app has entered a "logged out" state because it makes you unable to target the previously logged out user * with re-engagement campaigns. If you anticipate multiple users on the same device, but only want to target one * of them when your app is in a logged out state, we recommend separately keeping track of the user ID you want * to target while logged out and switching back to that user ID as part of your app's logout process. * * @param {string} userId - A unique identifier for this user. * @param {string} signature - An optional authentication signature to be used with the SDK Authentication feature. */ static changeUser(userId, signature) { this.bridge.changeUser( userId, signature != null ? signature : null ); } /** * Returns a unique ID stored for the user. * If the user is anonymous, there is no ID stored for the user and this method will return `null`. * * @param {function(error, result)} callback - A callback that receives the function call result. */ static getUserId(callback) { callFunctionWithCallback( this.bridge.getUserId, [], callback ); } /** * Sets the signature to be used to authenticate the current user. You can also set the signature when calling `changeUser`. * This signature will only have an effect if SDK Authentication is enabled. * * @param signature - The signature to add to network requests to authenticate the current user. */ static setSdkAuthenticationSignature(signature) { this.bridge.setSdkAuthenticationSignature(signature); } /** * An alias serves as an alternative unique user identifier. Use aliases to identify users along different * dimensions than your core user ID: * * Set a consistent identifier for analytics that will follow a given user both before and after they have * logged in to a mobile app or website. * * Add the identifiers used by a third party vendor to your Braze users in order to more easily reconcile * your data externally. * * Note: Each alias consists of two parts: a name for the identifier itself, and a label indicating the type of * alias. Users can have multiple aliases with different labels, but only one name per label. * * @param {string} aliasName - An identifier for alias name. * @param {string} aliasLabel - An identifier for alias label. */ static addAlias(aliasName, aliasLabel) { this.bridge.addAlias(aliasName, aliasLabel); } /** * @deprecated This method is deprecated in favor of `registerPushToken`. */ static registerAndroidPushToken(token) { if (Platform.OS === 'android') { this.bridge.registerPushToken(token); } } /** * This method posts a token to Braze's servers to associate the token with the current device. * @param {string} token - The device's push token. */ static registerPushToken(token) { this.bridge.registerPushToken(token); } /** * This method sets the Google Advertising ID and associated ad-tracking enabled field for this device. Note that the * SDK does not automatically collect this data. * * No-op on iOS. * * @param {string} googleAdvertisingId - The Google Advertising ID * @param {boolean} adTrackingEnabled - Whether ad-tracking is enabled for the Google Advertising ID */ static setGoogleAdvertisingId(googleAdvertisingId, adTrackingEnabled) { this.bridge.setAdTrackingEnabled( adTrackingEnabled, googleAdvertisingId ); } /** * Reports that the current user performed a custom named event. * @param {string} eventName - The identifier for the event to track. Best practice is to track generic events * useful for segmenting, instead of specific user actions (i.e. track watched_sports_video instead of * watched_video_adrian_peterson_td_mnf). Value is limited to 255 characters in length, cannot begin with a $, * and can only contain alphanumeric characters and punctuation. * @param {object} [eventProperties] - Hash of properties for this event. Keys are limited to 255 * characters in length, cannot begin with a $, and can only contain alphanumeric characters and punctuation. * Values can be numeric, boolean, Date, or strings 255 characters or shorter. */ static logCustomEvent(eventName, eventProperties) { parseNestedProperties(eventProperties); this.bridge.logCustomEvent(eventName, eventProperties); } /** * Reports that the current user made an in-app purchase. Useful for tracking and segmenting users. * @param {string} productId - A string identifier for the product purchased, e.g. an SKU. Value is limited to * 255 characters in length, cannot begin with a $, and can only contain alphanumeric characters and punctuation. * @param {float} price - The price paid. Base units depend on the currency. As an example, USD should be * reported as Dollars.Cents, whereas JPY should be reported as a whole number of Yen. All provided * values will be rounded to two digits with toFixed(2) * @param {string} [currencyCode=USD] - Currencies should be represented as an ISO 4217 currency code. Supported * currency symbols include: AED, AFN, ALL, AMD, ANG, AOA, ARS, AUD, AWG, AZN, BAM, BBD, BDT, BGN, BHD, BIF, * BMD, BND, BOB, BRL, BSD, BTC, BTN, BWP, BYR, BZD, CAD, CDF, CHF, CLF, CLP, CNY, COP, CRC, CUC, CUP, CVE, * CZK, DJF, DKK, DOP, DZD, EEK, EGP, ERN, ETB, EUR, FJD, FKP, GBP, GEL, GGP, GHS, GIP, GMD, GNF, GTQ, GYD, * HKD, HNL, HRK, HTG, HUF, IDR, ILS, IMP, INR, IQD, IRR, ISK, JEP, JMD, JOD, JPY, KES, KGS, KHR, KMF, KPW, * KRW, KWD, KYD, KZT, LAK, LBP, LKR, LRD, LSL, LTL, LVL, LYD, MAD, MDL, MGA, MKD, MMK, MNT, MOP, MRO, MTL, * MUR, MVR, MWK, MXN, MYR, MZN, NAD, NGN, NIO, NOK, NPR, NZD, OMR, PAB, PEN, PGK, PHP, PKR, PLN, PYG, QAR, * RON, RSD, RUB, RWF, SAR, SBD, SCR, SDG, SEK, SGD, SHP, SLL, SOS, SRD, STD, SVC, SYP, SZL, THB, TJS, TMT, * TND, TOP, TRY, TTD, TWD, TZS, UAH, UGX, USD, UYU, UZS, VEF, VND, VUV, WST, XAF, XAG, XAU, XCD, XDR, XOF, * XPD, XPF, XPT, YER, ZAR, ZMK, ZMW, and ZWL. Any other provided currency symbol will result in a logged * warning and no other action taken by the SDK. * @param {integer} [quantity=1] - The quantity of items purchased expressed as a whole number. Must be at least 1 * and at most 100. * @param {object} [purchaseProperties] - Hash of properties for this purchase. Keys are limited to 255 * characters in length, cannot begin with a $, and can only contain alphanumeric characters and punctuation. * Values can be numeric, boolean, Date, or strings 255 characters or shorter. */ static logPurchase( productId, price, currencyCode, quantity, purchaseProperties ) { parseNestedProperties(purchaseProperties); this.bridge.logPurchase( productId, price, currencyCode, quantity, purchaseProperties ); } // Braze user methods /** * Sets a custom user attribute. This can be any key/value pair and is used to collect extra information about the * user. * @param {string} key - The identifier of the custom attribute. Limited to 255 characters in length, cannot begin with * a $, and can only contain alphanumeric characters and punctuation. * @param value - Can be numeric, boolean, a Date object, a string, or an array of strings. Strings are limited to * 255 characters in length, cannot begin with a $, and can only contain alphanumeric characters and punctuation. * Passing a null value will remove this custom attribute from the user. * @param {function(error, result)} callback - A callback that receives the function call result. */ static setCustomUserAttribute(key, value, thirdParam, fourthParam) { const merge = typeof thirdParam === 'boolean' ? thirdParam : false; const callback = typeof thirdParam === 'boolean' ? fourthParam : thirdParam; var valueType = typeof value; if (value instanceof Date) { callFunctionWithCallback( this.bridge.setDateCustomUserAttribute, [key, Math.floor(value.getTime() / 1000)], callback ); } else if (value instanceof Array) { if (value.every(item => typeof item === 'string')) { callFunctionWithCallback( this.bridge.setCustomUserAttributeArray, [key, value], callback ); } else if (value.every(item => typeof item === 'object')) { callFunctionWithCallback( this.bridge.setCustomUserAttributeObjectArray, [key, value], callback ); } else { console.log(`User attribute ${value} was not a valid array. Custom attribute arrays can only contain all strings or all objects.`); } } else if (valueType === 'object') { callFunctionWithCallback( this.bridge.setCustomUserAttributeObject, [key, value, merge], callback ); } else if (valueType === 'boolean') { callFunctionWithCallback( this.bridge.setBoolCustomUserAttribute, [key, value], callback ); } else if (valueType === 'string') { callFunctionWithCallback( this.bridge.setStringCustomUserAttribute, [key, value], callback ); } else if (valueType === 'number') { if (parseInt(value) === parseFloat(value)) { callFunctionWithCallback( this.bridge.setIntCustomUserAttribute, [key, value], callback ); } else { callFunctionWithCallback( this.bridge.setDoubleCustomUserAttribute, [key, value], callback ); } } } /** * Increment/decrement the value of a custom attribute. Only numeric custom attributes can be incremented. Attempts to * increment a custom attribute that is not numeric be ignored. If you increment a custom attribute that has not * previously been set, a custom attribute will be created and assigned the value of incrementValue. To decrement * the value of a custom attribute, use a negative incrementValue. * @param {string} key - The identifier of the custom attribute. Limited to 255 characters in length, cannot begin with * a $, and can only contain alphanumeric characters and punctuation. * @param {integer} value - May be negative to decrement. * @param {function(error, result)} callback - A callback that receives the function call result. */ static incrementCustomUserAttribute(key, value, callback) { callFunctionWithCallback( this.bridge.incrementCustomUserAttribute, [key, value], callback ); } /** * Sets the first name of the user. * @param {string} firstName - Limited to 255 characters in length. */ static setFirstName(firstName) { this.bridge.setFirstName(firstName); } /** * Sets the last name of the user. * @param {string} lastName - Limited to 255 characters in length. */ static setLastName(lastName) { this.bridge.setLastName(lastName); } /** * Sets the email address of the user. * @param {string} email - Must pass RFC-5322 email address validation. */ static setEmail(email) { this.bridge.setEmail(email); } /** * Sets the gender of the user. * @param {Genders} gender - Options: f = female, m = male, n = N/A, o = other, p = prefer not to say, u = unknown * @param {function(error, result)} callback - A callback that receives the function call result. */ static setGender(gender, callback) { callFunctionWithCallback( this.bridge.setGender, [gender], callback ); } /** * Sets the language for the user. * @param {string} language - Should be valid ISO 639-1 language code. */ static setLanguage(language) { this.bridge.setLanguage(language); } /** * Sets the country for the user. * @param {string} country - Limited to 255 characters in length. */ static setCountry(country) { this.bridge.setCountry(country); } /** * Sets the home city for the user. * @param {string} homeCity - Limited to 255 characters in length. */ static setHomeCity(homeCity) { this.bridge.setHomeCity(homeCity); } /** * Sets the phone number of the user. * @param {string} phoneNumber - A phone number is considered valid if it is no more than 255 characters in length and * contains only numbers, whitespace, and the following special characters +.-() */ static setPhoneNumber(phoneNumber) { this.bridge.setPhoneNumber(phoneNumber); } /** * Sets the date of birth of the user. * @param {integer} year * @param {integer} month - 1-12 * @param {integer} day */ static setDateOfBirth(year, month, day) { this.bridge.setDateOfBirth(year, month, day); } /** * Adds the user to a subscription group. * @param {string} groupId - The string UUID corresponding to the subscription group, provided by the Braze dashboard. * @param {function(error, result)} callback - A callback that receives the function call result. */ static addToSubscriptionGroup(groupId, callback) { callFunctionWithCallback( this.bridge.addToSubscriptionGroup, [groupId], callback ); } /** * Removes the user from a subscription group. * @param {string} groupId - The string UUID corresponding to the subscription group, provided by the Braze dashboard. * @param {function(error, result)} callback - A callback that receives the function call result. */ static removeFromSubscriptionGroup(groupId, callback) { callFunctionWithCallback( this.bridge.removeFromSubscriptionGroup, [groupId], callback ); } /** * Sets whether the user should be sent push campaigns. * @param {NotificationSubscriptionTypes} notificationSubscriptionType - Notification setting (explicitly * opted-in, subscribed, or unsubscribed). * @param {function(error, result)} callback - A callback that receives the function call result. */ static setPushNotificationSubscriptionType( notificationSubscriptionType, callback ) { callFunctionWithCallback( this.bridge.setPushNotificationSubscriptionType, [notificationSubscriptionType], callback ); } /** * Sets whether the user should be sent email campaigns. * @param {NotificationSubscriptionTypes} notificationSubscriptionType - Notification setting (explicitly * opted-in, subscribed, or unsubscribed). * @param {function(error, result)} callback - A callback that receives the function call result. */ static setEmailNotificationSubscriptionType( notificationSubscriptionType, callback ) { callFunctionWithCallback( this.bridge.setEmailNotificationSubscriptionType, [notificationSubscriptionType], callback ); } /** * Adds a string to a custom atttribute string array, or creates that array if one doesn't exist. * @param {string} key - The identifier of the custom attribute. Limited to 255 characters in length, cannot begin with * a $, and can only contain alphanumeric characters and punctuation. * @param {string} value - The string to be added to the array. Strings are limited to 255 characters in length, cannot * begin with a $, and can only contain alphanumeric characters and punctuation. * @param {function(error, result)} callback - A callback that receives the function call result. */ static addToCustomUserAttributeArray(key, value, callback) { callFunctionWithCallback( this.bridge.addToCustomUserAttributeArray, [key, value], callback ); } /** * Removes a string from a custom attribute string array. * @param {string} key - The identifier of the custom attribute. Limited to 255 characters in length, cannot begin with * a $, and can only contain alphanumeric characters and punctuation. * @param {string} value - The string to be removed from the array. Strings are limited to 255 characters in length, * cannot beging with a $, and can only contain alphanumeric characters and punctuation. * @param {function(error, result)} callback - A callback that receives the function call result. */ static removeFromCustomUserAttributeArray(key, value, callback) { callFunctionWithCallback( this.bridge.removeFromCustomUserAttributeArray, [key, value], callback ); } /** * Unsets a custom user attribute. * @param {string} key - The identifier of the custom attribute. Limited to 255 characters in length, cannot begin with * a $, and can only contain alphanumeric characters and punctuation. * @param {function(error, result)} callback - A callback that receives the function call result. */ static unsetCustomUserAttribute(key, callback) { callFunctionWithCallback( this.bridge.unsetCustomUserAttribute, [key], callback ); } /** * Sets user attribution data. * * @param {string} network - The attribution network * @param {string} campaign - The attribution campaign * @param {string} adGroup - The attribution adGroup * @param {string} creative - The attribution creative */ static setAttributionData(network, campaign, adGroup, creative) { this.bridge.setAttributionData( network, campaign, adGroup, creative ); } // News Feed /** * Launches the News Feed UI element. */ static launchNewsFeed() { this.bridge.launchNewsFeed(); } /** * Returns an array of News Feed cards. * @returns {Promise<NewsFeedCard[]>} */ static getNewsFeedCards() { return this.bridge.getNewsFeedCards(); } /** * Manually log a click to Braze for a particular News Feed card. * The SDK will only log a card click when the card has the url property with a valid value. * @param {string} id */ static logNewsFeedCardClicked(id) { this.bridge.logNewsFeedCardClicked(id); } /** * Manually log an impression to Braze for a particular News Feed card. * @param {string} id */ static logNewsFeedCardImpression(id) { this.bridge.logNewsFeedCardImpression(id); } // Content Cards /** * Launches the Content Cards UI element. * * @param {boolean | undefined} dismissAutomaticallyOnCardClick * When enabled, the feed UI will automatically dismiss on scheme-based deep link clicks. * This setting is a no-op on Android, which already removes the Content Cards feed when opening a deep link. */ static launchContentCards(dismissAutomaticallyOnCardClick) { const dismissAutomatically = typeof dismissAutomaticallyOnCardClick === 'boolean' ? dismissAutomaticallyOnCardClick : false; this.bridge.launchContentCards(dismissAutomatically); } /** * Returns a content cards array after performing a refresh. * @returns {Promise<ContentCard[]>} */ static getContentCards() { return this.bridge.getContentCards(); } /** * Returns the most recent Content Cards array from the cache. * @returns {Promise<ContentCard[]>} */ static getCachedContentCards() { return this.bridge.getCachedContentCards(); } /** * Manually log a click to Braze for a particular card. * The SDK will only log a card click when the card has the url property with a valid value. * @param {string} id */ static logContentCardClicked(id) { this.bridge.logContentCardClicked(id); } /** * Manually log a dismissal to Braze for a particular card. * @param {string} id */ static logContentCardDismissed(id) { this.bridge.logContentCardDismissed(id); } /** * Manually log an impression to Braze for a particular card. * @param {string} id */ static logContentCardImpression(id) { this.bridge.logContentCardImpression(id); } /** * Perform the action of a particular card. * @param {string} id */ static processContentCardClickAction(id) { this.bridge.processContentCardClickAction(id); } /** * Requests a News Feed refresh. */ static requestFeedRefresh() { this.bridge.requestFeedRefresh(); } /** * Returns the current number of News Feed cards for the given category. * @param {CardCategory} category - Card category. Use Braze.CardCategory.ALL to get the total card count. * @param {function(error, result)} callback - A callback that receives the function call result. * Note that for Android, a successful result relies on a FeedUpdatedEvent being posted at least once. There is also a slight * race condition around calling changeUser, which requests a feed refresh, so the counts may not always be accurate. */ static getCardCountForCategories(category, callback) { callFunctionWithCallback( this.bridge.getCardCountForCategories, [category], callback ); } /** * Returns the number of unread News Feed cards for the given category. * @param {CardCategory} category - Card category. Use Braze.CardCategory.ALL to get the total unread card count. * @param {function(error, result)} callback - A callback that receives the function call result. * Note that for Android, a successful result relies on a FeedUpdatedEvent being posted at least once. There is also a slight * race condition around calling changeUser, which requests a feed refresh, so the counts may not always be accurate. */ static getUnreadCardCountForCategories(category, callback) { callFunctionWithCallback( this.bridge.getUnreadCardCountForCategories, [category], callback ); } // Banner Cards static getBanner(placementId) { return this.bridge.getBanner(placementId); } static requestBannersRefresh(placementIds) { this.bridge.requestBannersRefresh(placementIds); } // Flush Controls /** * Requests an immediate flush of any data waiting to be sent to Braze's servers. */ static requestImmediateDataFlush() { this.bridge.requestImmediateDataFlush(); } // Data Controls /** * Wipes Data on the Braze SDK. On iOS, the SDK will be disabled for the rest of the app run. */ static wipeData() { this.bridge.wipeData(); } /** * Disables the Braze SDK immediately. */ static disableSDK() { this.bridge.disableSDK(); } /** * Enables the Braze SDK after a previous call to disableSDK(). */ static enableSDK() { this.bridge.enableSDK(); } /** * Call this method once a user grants location permissions on Android * to initialize Braze location features. Calling this method is a no-op on * iOS. */ static requestLocationInitialization() { this.bridge.requestLocationInitialization(); } /** * Call this method to request a Braze Geofences update for a manually provided * GPS coordinate. Automatic Braze Geofence requests must be disabled to properly * use this method. Calling this method is a no-op on iOS. * @param {double} latitude - Location latitude. * @param {double} longitude - Location longitude. */ static requestGeofences(latitude, longitude) { this.bridge.requestGeofences(latitude, longitude); } /** * Sets a custom location attribute for the user. * @param {string} key - The identifier of the custom attribute. Limited to 255 characters in length, cannot begin with * a $, and can only contain alphanumeric characters and punctuation. * @param {double} latitude - Location latitude. * @param {double} longitude - Location longitude. * @param {function(error, result)} callback - A callback that receives the function call result. */ static setLocationCustomAttribute(key, latitude, longitude, callback) { callFunctionWithCallback( this.bridge.setLocationCustomAttribute, [key, latitude, longitude], callback ); } /** * Sets the last known location for the user. * For Android, latitude and longitude are required, with altitude, horizontal accuracy, and vertical accuracy being optional parameters. * For iOS, latitude, longitude, and horizontal accuracy are required, with altitude and vertical accuracy being optional parameters. * Calling this method with invalid parameters for a specific platform is a no-op. Latitude, longitude, and horizontal accuracy are the minimum required parameters to work for all platforms. * @param {number} latitude - Location latitude. Required. * @param {number} longitude - Location longitude. Required. * @param {number | null} altitude - Location altitude. May be null for both platforms. Providing an `altitude` requires a valid `verticalAccuracy` to be provided as well. * @param {number | null} horizontalAccuracy - Location horizontal accuracy. Equivalent to accuracy for Android. May be null for Android only; required for iOS. * @param {number | null} verticalAccuracy - Location vertical accuracy. May be null for both platforms unless `altitude` is supplied. */ static setLastKnownLocation(latitude, longitude, altitude, horizontalAccuracy, verticalAccuracy) { if (!horizontalAccuracy) { horizontalAccuracy = -1; } if (!verticalAccuracy) { verticalAccuracy = -1; } if (!altitude) { verticalAccuracy = -1; altitude = 0; } this.bridge.setLastKnownLocation(latitude, longitude, altitude, horizontalAccuracy, verticalAccuracy); } /** * Requests a refresh of the content cards from Braze's servers. */ static requestContentCardsRefresh() { this.bridge.requestContentCardsRefresh(); } /** * Call this method to have the SDK publish an "inAppMessageReceived" event containing the in-app message data to the * Javascript layer. You can listen to this event with `Braze.addListener()`. * * @param {boolean} useBrazeUI - Whether to use the default Braze UI for in-app messages. * @param {function(event)} subscriber - The method to call when an in-app message is received. */ static subscribeToInAppMessage(useBrazeUI, subscriber) { let withBrazeUI = false; if (useBrazeUI != null) { withBrazeUI = useBrazeUI; } this.bridge.subscribeToInAppMessage(withBrazeUI, subscriber); if (typeof subscriber === "function") { return this.eventEmitter.addListener(Events.IN_APP_MESSAGE_RECEIVED, subscriber); } } /** * Dismisses the currently displayed in app message. */ static hideCurrentInAppMessage() { this.bridge.hideCurrentInAppMessage(); } /** * Logs a click for the provided in-app message data * @param {InAppMessage} inAppMessage */ static logInAppMessageClicked(inAppMessage) { const inAppMessageString = inAppMessage.toString(); this.bridge.logInAppMessageClicked(inAppMessageString); } /** * Logs an impression for the provided in-app message data * @param {InAppMessage} inAppMessage */ static logInAppMessageImpression(inAppMessage) { const inAppMessageString = inAppMessage.toString(); this.bridge.logInAppMessageImpression(inAppMessageString); } /** * Logs a button click for the provided in-app message button data * @param {InAppMessage} inAppMessage * @param {number} buttonId */ static logInAppMessageButtonClicked(inAppMessage, buttonId) { const inAppMessageString = inAppMessage.toString(); this.bridge.logInAppMessageButtonClicked( inAppMessageString, buttonId ); } /** * Perform the action of an in-app message button * @param {InAppMessage} inAppMessage * @param {number} ID of the button. */ static performInAppMessageButtonAction(inAppMessage, buttonId) { console.log('Processing In-App Message Button Action: ', inAppMessage, ' ', buttonId); const inAppMessageString = inAppMessage.toString(); this.bridge.performInAppMessageAction(inAppMessageString, buttonId); } /** * Perform the action of an in-app message * @param {InAppMessage} inAppMessage */ static performInAppMessageAction(inAppMessage) { console.log('Processing In-App Message Action: ', inAppMessage); const inAppMessageString = inAppMessage.toString(); this.bridge.performInAppMessageAction(inAppMessageString, -1); } /** * Requests a push permission prompt. On Android 12 and below, this is a no-op. * * @param {*} permissionOptions */ static requestPushPermission(permissionOptions) { if (!permissionOptions) { permissionOptions = { "alert": true, "badge": true, "sound": true, "provisional": false } } this.bridge.requestPushPermission(permissionOptions); } /** * Returns feature flags array * @returns {Promise<FeatureFlag[]>} */ static getAllFeatureFlags() { return this.bridge.getAllFeatureFlags(); } /** * Returns feature flag * @returns {Promise<FeatureFlag|null>} */ static getFeatureFlag(id) { return this.bridge.getFeatureFlag(id); } /** * Requests a refresh of Feature Flags from the Braze server. */ static refreshFeatureFlags() { this.bridge.refreshFeatureFlags(); } /** * Logs an impression for the Feature Flag with the provided ID. */ static logFeatureFlagImpression(id) { this.bridge.logFeatureFlagImpression(id); } /** * Returns the boolean property for the given feature flag ID. * @returns {Promise<boolean|null>} */ static getFeatureFlagBooleanProperty(id, key) { return this.bridge.getFeatureFlagBooleanProperty(id, key); } /** * Returns the string property for the given feature flag ID. * @returns {Promise<string|null>} */ static getFeatureFlagStringProperty(id, key) { return this.bridge.getFeatureFlagStringProperty(id, key); } /** * Returns the number property for the given feature flag ID. * @returns {Promise<number|null>} */ static getFeatureFlagNumberProperty(id, key) { return this.bridge.getFeatureFlagNumberProperty(id, key); } /** * Returns the timestamp property for the given feature flag ID. * @returns {Promise<number|null>} */ static getFeatureFlagTimestampProperty(id, key) { return this.bridge.getFeatureFlagTimestampProperty(id, key); } /** * Returns the JSON property for the given feature flag ID. * @returns {Promise<object|null>} */ static getFeatureFlagJSONProperty(id, key) { return this.bridge.getFeatureFlagJSONProperty(id, key); } /** * Returns the image property for the given feature flag ID. * @returns {Promise<string|null>} */ static getFeatureFlagImageProperty(id, key) { return this.bridge.getFeatureFlagImageProperty(id, key); } /** * This method informs Braze whether ad-tracking has been enabled for this device. Note that the SDK does not * automatically collect this data. * * @param {string} adTrackingEnabled - Whether ad-tracking is enabled. * @param {string} googleAdvertisingId - The Google Advertising ID. (Android only) */ static setAdTrackingEnabled(adTrackingEnabled, googleAdvertisingId) { return this.bridge.setAdTrackingEnabled( adTrackingEnabled, googleAdvertisingId ); } /** * This method passes the Identifier For Advertiser (IDFA) to Braze for iOS. It is a no-op on Android. * * See Apple's docs on [App Tracking Transparency](https://apple.co/3LM7mm2) for more information. * * @param {string} identifierForAdvertiser - The IDFA. */ static setIdentifierForAdvertiser(identifierForAdvertiser) { return this.bridge.setIdentifierForAdvertiser(identifierForAdvertiser); } /** * This method passes the Identifier For Vendor (IDFV) to Braze for iOS. It is a no-op on Android. * * @param {string} identifierForVendor - The IDFV. */ static setIdentifierForVendor(identifierForVendor) { return this.bridge.setIdentifierForVendor(identifierForVendor); } /** * Updates the list of data types you wish to declare or remove as tracked user data. * * For more details, refer to Braze's [Privacy Manifest documentation](https://www.braze.com/docs/developer_guide/platform_integration_guides/swift/privacy_manifest/). * * No-op on Android. * * @param {TrackingPropertyAllowList} allowList - The list of tracking properties to update. */ static updateTrackingPropertyAllowList(allowList) { if (allowList.adding && !this.isValidTrackingPropertyArray(allowList.adding)) { console.log("'adding' property must be an array of strings. Setting array to empty."); allowList.adding = []; } if (allowList.removing && !this.isValidTrackingPropertyArray(allowList.removing)) { console.log("'removing' property must be an array of strings. Setting array to empty."); allowList.removing = []; } if (allowList.addingCustomEvents && !this.isValidTrackingPropertyArray(allowList.addingCustomEvents)) { console.log("'addingCustomEvents' property must be an array of strings. Setting array to empty."); allowList.addingCustomEvents = []; } if (allowList.removingCustomEvents && !this.isValidTrackingPropertyArray(allowList.removingCustomEvents)) { console.log("'removingCustomEvents' property must be an array of strings. Setting array to empty."); allowList.removingCustomEvents = []; } if (allowList.addingCustomAttributes && !this.isValidTrackingPropertyArray(allowList.addingCustomAttributes)) { console.log("'addingCustomAttributes' property must be an array of strings. Setting array to empty."); allowList.addingCustomAttributes = []; } if (allowList.removingCustomAttributes && !this.isValidTrackingPropertyArray(allowList.removingCustomAttributes)) { console.log("'removingCustomAttributes' property must be an array of strings. Setting array to empty."); allowList.removingCustomAttributes = []; } return this.bridge.updateTrackingPropertyAllowList(allowList); } // Events /** * Subscribes to the specific SDK event. * When you want to stop listening, call `.remove()` on the returned * subscription. * @param {Events} event * @param {function} subscriber */ static addListener(event, subscriber) { if (Platform.OS === 'android') { this.bridge.addListener(event); } return this.eventEmitter.addListener(event, subscriber); } // Helper Functions /** * Validates an array to be processed in the `TrackingPropertyAllowList`. * * @param {array} array * @returns Whether the array is valid according to the tracking property allow list. */ static isValidTrackingPropertyArray(array) { return Array.isArray(array) && array.every(item => typeof item === 'string'); } }