React Native
Installation
yarn add @thanksjs/react-native-webview react-native-webviewUsage
import { ThanksWidget } from '@thanksjs/react-native-webview';
/// somewhere in your code
<ThanksWidget partnerId="{your partner id}" />;It's all comes with TypeScript support, dont worry.
Parameters
Refer to the full Thanks API configuration documentation for more.
Advanced usage
The important parts are:
- providing a customer
email. Strictly sha256 hash will be transferred during the widget lifecycle. No sensitive information leaves your application without your permission. - giving permission to send Personal Information to improve efficiency of communications
subjectandinfocan be used to decide what information to sendsubjectcan benotificationorautofillof visible UI elements
info.tokenis a unique identifier for the request and can be used to trace PII flow further in our systems
keywords,categoryanditemsare used to fine-tune ads to display
<ThanksWidget
partnerId="{your partner id}"
// information for the first scren
statusText="Your order has been confirmed"
emailHash={{ sha256: customersEmailHash }}
// or
email={customerEmail}
onPersonalInformationRequest={(subject, info) => {
return {
email,
firstName: 'TestUser',
};
}}
onDisplay={() => {
console.log('widget displayed');
}}
onClose={() => {
console.log('widget closed');
}}
keywords={['violet', 'roses', 'blueberry']}
items={[
{
name: 'Flatwhite',
value: 4.0,
currency: 'AUD',
quantity: 2,
type: 'coffee',
category: 'drinks',
subcategory: 'australian-coffee',
},
]}
categories={['lifestyle']}
/>Using onLinkClick
onLinkClickconst [inAppUrl, setInAppUrl] = useState<string | null>(null);
<ThanksWidget
// ... other configuration parameters above
onLinkClick={(url) => {
// Keep deep links in-your-own-app: render content inside the Thanks modal
// via `children` instead of leaving the app.
if (url.startsWith('myapp://') || url.includes('offers.myapp.com')) {
setInAppUrl(url);
return false; // your app handles it, Thanks will NOT call Linking.openURL
}
// Everything else: let Thanks open it (equivalent to
// `Linking.openURL(url)`).
return true;
}}
// ... other configuration parameters above
/>Controlling layering and visibility (wrapperComponent)
wrapperComponent)The React Native SDK wraps the widget WebView in React Native's Modal by default. If you need to control z-index or temporarily move the widget out of frame at runtime, e.g. for example, while an in-app browser is open, you can replace the wrapper with your own component.
The wrapper receives { children, onRequestClose, animationType, transparent, isReady }. Because it's a normal React component, it can hold its own state and re-render to reposition the widget without closing it.
import { useState } from 'react';
import { View } from 'react-native';
import { ThanksWidget } from '@thanksjs/react-native-webview';
const CustomWrapper = ({ children, isReady }) => {
const [behind, setBehind] = useState(false);
globalThis.__setWidgetBehind = setBehind;
return (
<View
style={{
position: 'absolute',
top: 0, left: 0, right: 0, bottom: 0,
zIndex: behind ? -1 : 9999,
display: isReady ? 'flex' : 'none',
}}
>
{children}
</View>
);
};
<ThanksWidget
partnerId="YOUR_PARTNER_ID"
wrapperComponent={CustomWrapper}
onLinkClick={(url) => {
globalThis.__setWidgetBehind(true);
openInAppBrowser(url, {
onClose: () => globalThis.__setWidgetBehind(false),
});
return false;
}}
/>;wrapperComponent is also accepted by ThanksWidgetController and thanksWidget.open(). When set in both places, the value passed to open() wins.
Note
style.zIndexandoffsetTopruntime updates are for the Web SDK only. For the React Native SDK, usewrapperComponentfor layering and positioning control. While we plan to improve this, the wrapper pattern is the supported approach.
Indirect usage
Sometimes an event-based solution is easier to manage, in this case we handle some state management for you.
import { ThanksWidgetController, thanksWidget } from '@thanksjs/react-native-webview';
const YourApplication = () => (
<>
{someCode}
// put AFTER all other views, so it will be displayed on top
<ThanksWidgetController partnerId="your-id" />
</>
);
const YourThanksPage = () => {
useEffect(
() => {
// ThanksWidgetController will render Widget instantly
// if ThanksWidgetController is not present this will throw an error
thanksWidget.open(thanksConfiguration);
// and hide when you navigate away from the page
return () => thanksWidget.close();
},
[
// important to keep dependencies free to prevent re-rendering widget
// as customer's journey will be reset
],
);
return pageCode;
};Adding a Block
A Block is a permanently embedded element in your application interface.
If you prefer to embed a ThanksBlock into your application, you can following the example below:
import { ThanksBlock } from '@thanksjs/react-native-webview';
/// somewhere in your code
<View style={{ width, height }}>
<ThanksBlock partnerId="YOUR_PARTNER_ID" />
</View>;In the above example, we wrap the ThanksBlock to set its height and width.
Error handling
You can observe and react to errors in the components with the optional onError prop.
<ThanksWidget
partnerId="YOUR_PARTNER_ID"
onError={(err) => {
// ThanksSdkError
}}
/>
<ThanksBlock
partnerId="YOUR_PARTNER_ID"
slot="main"
onError={(err) => {
// ThanksSdkError
}}
/>Error codes:
WebviewError: WebView failure (network, HTTP, or page crash/termination).StartupTimeout: Widget did not become ready within the startup time limit.LoadingError: Loading failed before the widget was ready.TargetResolveFailed: Failed to resolve the widget or block URL target.CooldownFetchFailed: Failed to fetch cooldown state (e.g. cooldown).PiiRequestFailed:onPersonalInformationRequestcallback threw or rejected.
Dealing with 'RNCWebView' could not be found
'RNCWebView' could not be foundIn this package, we use react-native-webview to embed our Widget within your application.
Since react-native-webview is a native module, you'll need to ensure react-native-webview is properly linked as a native module. For the following examples, we'll assume you use Expo. If you don't use Expo, you can apply the same steps to your workflow.
Option 1: Install react-native-webview
react-native-webviewStep 1: Install react-native-webview
react-native-webviewnpm install react-native-webviewStep 2: Re-run the Prebuild Command
Now, run the prebuild command again:
expo prebuildStep 3: Run the Custom Development Client
Follow the previous steps to build your custom development client:
expo run:iosOR
expo run:androidBy doing this, we force Expo to add Expo Modules to the iOS Podfile (and build.gradle for Android)
Option 2: Manually install react-native-webview
react-native-webviewIf you do not want to add another dependency to your project, we recommend you manually link the native modules to your Native app's output.
Step 1: Add react-native-webview to your Podfile.
react-native-webview to your Podfile.target 'YourProjectName' do
# ... (other existing pods)
pod 'react-native-webview', :path => '../node_modules/react-native-webview'
endStep 2: Clean the project and reinstall the pods
npx expo prebuild --clean
cd ios && pod install && cd ..Step 3: Run the development client
npx expo run:iosUpdated 3 days ago