@adadapted/react-native-sdk 3.1.11 → 3.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,208 +1,237 @@
1
- function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
2
1
  /**
3
2
  * Component for creating an {@link AdZone}.
4
3
  * @module
5
4
  */
6
5
  import * as React from "react";
7
- import { Linking, StyleSheet, View } from "react-native";
6
+ import { DeviceEventEmitter, Linking, StyleSheet, View } from "react-native";
8
7
  import * as adadaptedApiRequests from "../api/adadaptedApiRequests";
9
8
  import { AdActionType, ReportedEventType } from "../api/adadaptedApiTypes";
10
9
  import { WebView } from "react-native-webview";
11
10
  import { safeInvoke } from "../util";
11
+ import { useEffect, useState } from "react";
12
12
 
13
13
  /**
14
14
  * Props interface for {@link AdZone}.
15
15
  */
16
16
 
17
+ /**
18
+ * Timer used for cycling through ads in the zone
19
+ * based on the ad "refresh time" for each ad.
20
+ */
21
+ let cycleAdTimer;
22
+
17
23
  /**
18
24
  * Creates the AdZone component.
25
+ * @param props - properties passed to AdZone.
26
+ * @returns an AdZone JSX Element.
19
27
  */
20
- export class AdZone extends React.Component {
21
- /**
22
- * Timer used for cycling through ads in the zone
23
- * based on the ad "refresh time" for each ad.
24
- */
28
+ export function AdZone(props) {
29
+ // Generates a random number between 0 and (number of available ads - 1).
30
+ const startingAdIndex = Math.floor(Math.random() * props.adZoneData.ads.length);
25
31
 
26
32
  /**
27
- * @inheritDoc
33
+ * Tracks the current ad index being shown.
28
34
  */
29
- constructor(props, context) {
30
- super(props, context);
31
-
32
- // Generates a random number between 0 and (number of available ads - 1).
33
- _defineProperty(this, "cycleAdTimer", void 0);
34
- const startingAdIndex = Math.floor(Math.random() * this.props.adZoneData.ads.length);
35
- this.state = {
36
- adIndexShown: startingAdIndex,
37
- touchStartCoords: undefined
38
- };
39
- }
40
-
35
+ const [adIndexShown, setAdIndexShown] = useState(startingAdIndex);
41
36
  /**
42
- * @inheritDoc
37
+ * Tracks the coordinates when the user started touching the Ad View.
43
38
  */
44
- componentDidMount() {
45
- this.initializeAd();
46
- }
47
-
39
+ const [touchStartCoords, setTouchStartCoords] = useState({
40
+ x: 0,
41
+ y: 0
42
+ });
48
43
  /**
49
- * @inheritDoc
44
+ * Track ad visibility (for off-screen ads).
50
45
  */
51
- componentWillUnmount() {
52
- if (this.cycleAdTimer) {
53
- clearTimeout(this.cycleAdTimer);
46
+ const [isAdVisible, setIsAdVisibile] = useState(props.defaultToInvisibleAdZone ? false : true);
47
+
48
+ // - Define all useEffect triggers.
49
+ useEffect(() => {
50
+ DeviceEventEmitter.addListener("visibility-event", event => {
51
+ setIsAdVisibile(event);
52
+ });
53
+ DeviceEventEmitter.addListener("acknowledge", itemName => {
54
+ acknowledge(itemName);
55
+ });
56
+ return () => {
57
+ clearTimeout(cycleAdTimer);
58
+ DeviceEventEmitter.removeAllListeners("visibility-event");
59
+ DeviceEventEmitter.removeAllListeners("acknowledge");
60
+ };
61
+ }, []);
62
+ useEffect(() => {
63
+ startAdTimer();
64
+ if (isAdVisible) {
65
+ sendAdImpression();
54
66
  }
55
- }
67
+ }, [adIndexShown]);
68
+ useEffect(() => {
69
+ if (isAdVisible) {
70
+ sendAdImpression();
71
+ }
72
+ }, [isAdVisible]);
56
73
 
57
74
  /**
58
- * @inheritDoc
75
+ * Generates all component related styles.
76
+ * @returns the styles needed for the component.
59
77
  */
60
- render() {
61
- // Generate the styles each render in case the ad is updated with
62
- // new settings that need to be reflected in the styles of the view.
63
- const styles = this.generateStyles();
64
- const currentAd = this.props.adZoneData.ads[this.state.adIndexShown] || undefined;
65
- const finalMainViewStyle = styles.mainView;
66
- if (!currentAd || !currentAd.creative_url) {
67
- // If there is no ad to display, make the view take up no space.
68
- finalMainViewStyle.width = 0;
69
- finalMainViewStyle.height = 0;
70
- }
71
- return /*#__PURE__*/React.createElement(View, {
72
- style: finalMainViewStyle
73
- }, currentAd && currentAd.creative_url ? /*#__PURE__*/React.createElement(WebView, {
74
- source: {
75
- uri: currentAd.creative_url
76
- },
77
- androidLayerType: "hardware",
78
- automaticallyAdjustContentInsets: false,
79
- style: styles.webView,
80
- onTouchStart: e => {
81
- this.setState({
82
- touchStartCoords: {
83
- x: e.nativeEvent.pageX,
84
- y: e.nativeEvent.pageY
85
- }
86
- });
78
+ function generateStyles() {
79
+ return StyleSheet.create({
80
+ mainView: {
81
+ width: "100%",
82
+ height: "100%"
87
83
  },
88
- onTouchEnd: e => {
89
- if (this.state.touchStartCoords) {
90
- const touchEndCoords = {
91
- x: e.nativeEvent.pageX,
92
- y: e.nativeEvent.pageY
93
- };
94
- if (Math.abs(this.state.touchStartCoords.x - touchEndCoords.x) < this.props.xyDragDistanceAllowed && Math.abs(this.state.touchStartCoords.y - touchEndCoords.y) < this.props.xyDragDistanceAllowed) {
95
- this.onAdZoneSelected(currentAd);
96
- }
97
-
98
- // Make sure to reset the start coords
99
- this.setState({
100
- touchStartCoords: undefined
101
- });
102
- }
84
+ webView: {
85
+ width: "100%",
86
+ height: "100%"
103
87
  }
104
- }) : undefined);
88
+ });
89
+ }
90
+
91
+ // Generate the styles each render in case the ad is updated with
92
+ // new settings that need to be reflected in the styles of the view.
93
+ const styles = generateStyles();
94
+ const currentAd = props.adZoneData.ads[adIndexShown] || undefined;
95
+ const finalMainViewStyle = styles.mainView;
96
+ if (!currentAd || !currentAd.creative_url) {
97
+ // If there is no ad to display, make the view take up no space.
98
+ finalMainViewStyle.width = "0";
99
+ finalMainViewStyle.height = "0";
105
100
  }
106
101
 
107
102
  /**
108
103
  * Triggers when the user selects the ad zone.
109
- * @param currentAd - The ad currently displayed.
104
+ * @param currentlyDisplayedAd - The ad currently displayed.
110
105
  */
111
- onAdZoneSelected(currentAd) {
106
+ function onAdZoneSelected(currentlyDisplayedAd) {
112
107
  // Determine the "action type" and perform that specific action.
113
- if (currentAd.action_type === AdActionType.EXTERNAL && currentAd.action_path) {
108
+ if (currentlyDisplayedAd.action_type === AdActionType.EXTERNAL && currentlyDisplayedAd.action_path) {
114
109
  // Action Type: EXTERNAL
115
- Linking.openURL(currentAd.action_path).then();
116
- } else if (currentAd.action_type === AdActionType.CONTENT && currentAd.payload && currentAd.payload.detailed_list_items) {
117
- safeInvoke(this.props.onAddToListTriggered, currentAd.payload.detailed_list_items);
110
+ Linking.openURL(currentlyDisplayedAd.action_path).then();
111
+ } else if (currentlyDisplayedAd.action_type === AdActionType.CONTENT && currentlyDisplayedAd.payload && currentlyDisplayedAd.payload.detailed_list_items) {
112
+ safeInvoke(props.onAddToListTriggered, currentlyDisplayedAd.payload.detailed_list_items);
118
113
  }
119
- this.triggerReportAdEvent(currentAd, ReportedEventType.INTERACTION);
120
- if (this.cycleAdTimer) {
121
- clearTimeout(this.cycleAdTimer);
114
+ cycleDisplayedAd();
115
+ }
116
+
117
+ /**
118
+ * Call to acknowledge ATL item(s) added to user list.
119
+ * @param itemName - Detailed list item title from ad that was clicked.
120
+ */
121
+ function acknowledge(itemName) {
122
+ if (props.adZoneData.ads) {
123
+ props.adZoneData.ads.forEach(ad => {
124
+ ad.payload.detailed_list_items.forEach(item => {
125
+ if (item.product_title === itemName) {
126
+ triggerReportAdEvent(ad, ReportedEventType.INTERACTION);
127
+ }
128
+ });
129
+ });
122
130
  }
123
- this.cycleDisplayedAd();
124
131
  }
125
132
 
126
133
  /**
127
134
  * Triggered when we need to report an ad event to the API.
128
- * @param currentAd - The ad to send an event for.
135
+ * @param ad - The ad to send an event for.
129
136
  * @param eventType - The event type for the reported event.
130
137
  */
131
- triggerReportAdEvent(currentAd, eventType) {
138
+ function triggerReportAdEvent(ad, eventType) {
132
139
  // The event timestamp has to be sent as a unix timestamp.
133
140
  const currentTs = Math.round(new Date().getTime() / 1000);
134
141
 
135
142
  // Log the taken action/event with the API.
136
143
  adadaptedApiRequests.reportAdEvent({
137
- app_id: this.props.appId,
138
- session_id: this.props.sessionId,
139
- udid: this.props.udid,
144
+ app_id: props.appId,
145
+ session_id: props.sessionId,
146
+ udid: props.udid,
140
147
  events: [{
141
- ad_id: currentAd.ad_id,
142
- impression_id: currentAd.impression_id,
148
+ ad_id: ad.ad_id,
149
+ impression_id: ad.impression_id,
143
150
  event_type: eventType,
144
151
  created_at: currentTs
145
152
  }]
146
- }, this.props.deviceOs, this.props.apiEnv).then(() => {
153
+ }, props.deviceOs, props.apiEnv).then(() => {
147
154
  // Do nothing with the response for now...
148
155
  });
149
156
  }
150
157
 
151
158
  /**
152
159
  * Generates a new timer for cycling to the next ad.
153
- * @param timerLength - The length of time(in milliseconds) to initialize
154
- * the timer with.
155
160
  */
156
- createAdTimer(timerLength) {
157
- if (this.props.adZoneData.ads.length > 0) {
158
- this.cycleAdTimer = setTimeout(() => {
159
- this.cycleDisplayedAd();
160
- }, timerLength);
161
+ function startAdTimer() {
162
+ clearTimeout(cycleAdTimer);
163
+ if (props.adZoneData.ads.length > 0) {
164
+ const refreshTime = props.adZoneData.ads[adIndexShown].refresh_time * 1000;
165
+ cycleAdTimer = setTimeout(cycleDisplayedAd, refreshTime);
161
166
  }
162
167
  }
163
168
 
164
169
  /**
165
170
  * Cycles to the next ad to display in the current available sequence of ads.
166
171
  */
167
- cycleDisplayedAd() {
172
+ function cycleDisplayedAd() {
168
173
  // Start by determining the next ad index to display.
169
174
  let nextAdIndex = 0;
170
- if (this.state.adIndexShown < this.props.adZoneData.ads.length - 1) {
171
- nextAdIndex = this.state.adIndexShown + 1;
175
+ const lastAd = props.adZoneData.ads[adIndexShown];
176
+ if (adIndexShown < props.adZoneData.ads.length - 1) {
177
+ nextAdIndex = adIndexShown + 1;
172
178
  }
173
- this.setState({
174
- adIndexShown: nextAdIndex
175
- }, () => {
176
- this.initializeAd();
177
- });
179
+ if (nextAdIndex !== adIndexShown && lastAd.impression_tracked) {
180
+ // Reset ad impression tracking status.
181
+ lastAd.impression_tracked = false;
182
+ } else {
183
+ // Send invisible ad impression if ad was not visible before end of timer cycle.
184
+ triggerReportAdEvent(lastAd, ReportedEventType.INVISIBLE_IMPRESSION);
185
+ }
186
+ setAdIndexShown(nextAdIndex);
178
187
  }
179
188
 
180
189
  /**
181
- * Performs all ad initialization tasks when a new ad is being displayed.
190
+ * Send ad tracking impression.
182
191
  */
183
- initializeAd() {
184
- // Create the new timer based on the new ad index.
185
- this.createAdTimer(this.props.adZoneData.ads[this.state.adIndexShown].refresh_time * 1000);
192
+ function sendAdImpression() {
193
+ const ad = props.adZoneData.ads[adIndexShown];
186
194
 
187
195
  // Trigger an impression event for the ad.
188
- this.triggerReportAdEvent(this.props.adZoneData.ads[this.state.adIndexShown], ReportedEventType.IMPRESSION);
196
+ if (!ad.impression_tracked) {
197
+ triggerReportAdEvent(ad, ReportedEventType.IMPRESSION);
198
+ ad.impression_tracked = true;
199
+ }
189
200
  }
190
201
 
191
- /**
192
- * Generates all component related styles.
193
- * @returns the styles needed for the component.
194
- */
195
- generateStyles() {
196
- return StyleSheet.create({
197
- mainView: {
198
- width: "100%",
199
- height: "100%"
200
- },
201
- webView: {
202
- width: "100%",
203
- height: "100%"
202
+ // Returned JSX.
203
+ return /*#__PURE__*/React.createElement(View, {
204
+ style: finalMainViewStyle
205
+ }, currentAd && currentAd.creative_url ? /*#__PURE__*/React.createElement(WebView, {
206
+ source: {
207
+ uri: currentAd.creative_url
208
+ },
209
+ androidLayerType: "hardware",
210
+ automaticallyAdjustContentInsets: false,
211
+ style: styles.webView,
212
+ onTouchStart: e => {
213
+ setTouchStartCoords({
214
+ x: e.nativeEvent.pageX,
215
+ y: e.nativeEvent.pageY
216
+ });
217
+ },
218
+ onTouchEnd: e => {
219
+ if (touchStartCoords) {
220
+ const touchEndCoords = {
221
+ x: e.nativeEvent.pageX,
222
+ y: e.nativeEvent.pageY
223
+ };
224
+ if (Math.abs(touchStartCoords.x - touchEndCoords.x) < props.xyDragDistanceAllowed && Math.abs(touchStartCoords.y - touchEndCoords.y) < props.xyDragDistanceAllowed) {
225
+ onAdZoneSelected(currentAd);
226
+ }
227
+
228
+ // Make sure to reset the start coords
229
+ setTouchStartCoords({
230
+ x: 0,
231
+ y: 0
232
+ });
204
233
  }
205
- });
206
- }
234
+ }
235
+ }) : undefined);
207
236
  }
208
237
  //# sourceMappingURL=AdZone.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["React","Linking","StyleSheet","View","adadaptedApiRequests","AdActionType","ReportedEventType","WebView","safeInvoke","AdZone","Component","constructor","props","context","startingAdIndex","Math","floor","random","adZoneData","ads","length","state","adIndexShown","touchStartCoords","undefined","componentDidMount","initializeAd","componentWillUnmount","cycleAdTimer","clearTimeout","render","styles","generateStyles","currentAd","finalMainViewStyle","mainView","creative_url","width","height","uri","webView","e","setState","x","nativeEvent","pageX","y","pageY","touchEndCoords","abs","xyDragDistanceAllowed","onAdZoneSelected","action_type","EXTERNAL","action_path","openURL","then","CONTENT","payload","detailed_list_items","onAddToListTriggered","triggerReportAdEvent","INTERACTION","cycleDisplayedAd","eventType","currentTs","round","Date","getTime","reportAdEvent","app_id","appId","session_id","sessionId","udid","events","ad_id","impression_id","event_type","created_at","deviceOs","apiEnv","createAdTimer","timerLength","setTimeout","nextAdIndex","refresh_time","IMPRESSION","create"],"sources":["AdZone.tsx"],"sourcesContent":["/**\n * Component for creating an {@link AdZone}.\n * @module\n */\nimport * as React from \"react\";\nimport { Linking, StyleSheet, View, ViewStyle } from \"react-native\";\nimport * as adadaptedApiRequests from \"../api/adadaptedApiRequests\";\nimport {\n Ad,\n AdActionType,\n DetailedListItem,\n ReportedEventType,\n Zone,\n} from \"../api/adadaptedApiTypes\";\nimport { WebView } from \"react-native-webview\";\nimport { ApiEnv, DeviceOS } from \"../index\";\nimport { safeInvoke } from \"../util\";\n\n/**\n * Props interface for {@link AdZone}.\n */\ninterface Props {\n /**\n * The app ID.\n */\n appId: string;\n /**\n * The session ID.\n */\n sessionId: string;\n /**\n * The UDID.\n */\n udid: string;\n /**\n * The touch sensitivity of the Ad Zone in both the X and Y directions.\n * This is used to determine the click/press sensitivity when the\n * Ad Zone is being touched by the user as a regular touch or while\n * scrolling the view. If the amount of touch \"drag\" distance in either\n * X or Y direction is less than this value, we will treat the action as\n * a click/press on the Ad Zone.\n */\n xyDragDistanceAllowed: number;\n /**\n * The device OS used for API requests.\n */\n deviceOs: DeviceOS;\n /**\n * The API environment to use when making an API request.\n */\n apiEnv: ApiEnv;\n /**\n * The ad zone data.\n */\n adZoneData: Zone;\n /**\n * Callback that gets triggered when an \"add to list\" item/items are clicked.\n * @param items - The array of items to \"add to list\".\n */\n onAddToListTriggered?(items: DetailedListItem[]): void;\n}\n\n/**\n * State interface for {@link AdZone}.\n */\ninterface State {\n /**\n * Tracks the current ad index being shown.\n */\n adIndexShown: number;\n /**\n * Tracks the coordinates when the user started touching the Ad View.\n */\n touchStartCoords: TouchCoordinates | undefined;\n}\n\n/**\n * Interface for tracking \"touch\" coordinates.\n */\ninterface TouchCoordinates {\n /**\n * The X coordinate for the touch.\n */\n x: number;\n /**\n * The Y coordinate for the touch.\n */\n y: number;\n}\n\n/**\n * Defines the style typing for the component.\n */\ninterface StyleDef {\n /**\n * Styles for the main View element.\n */\n mainView: ViewStyle;\n /**\n * Styles for the WebView element.\n */\n webView: ViewStyle;\n}\n\n/**\n * Creates the AdZone component.\n */\nexport class AdZone extends React.Component<Props, State> {\n /**\n * Timer used for cycling through ads in the zone\n * based on the ad \"refresh time\" for each ad.\n */\n private cycleAdTimer: ReturnType<typeof setTimeout> | undefined;\n\n /**\n * @inheritDoc\n */\n constructor(props: Props, context?: any) {\n super(props, context);\n\n // Generates a random number between 0 and (number of available ads - 1).\n const startingAdIndex = Math.floor(\n Math.random() * this.props.adZoneData.ads.length\n );\n\n this.state = {\n adIndexShown: startingAdIndex,\n touchStartCoords: undefined,\n };\n }\n\n /**\n * @inheritDoc\n */\n public componentDidMount(): void {\n this.initializeAd();\n }\n\n /**\n * @inheritDoc\n */\n public componentWillUnmount(): void {\n if (this.cycleAdTimer) {\n clearTimeout(this.cycleAdTimer);\n }\n }\n\n /**\n * @inheritDoc\n */\n public render(): JSX.Element {\n // Generate the styles each render in case the ad is updated with\n // new settings that need to be reflected in the styles of the view.\n const styles = this.generateStyles();\n const currentAd: Ad | undefined =\n this.props.adZoneData.ads[this.state.adIndexShown] || undefined;\n const finalMainViewStyle = styles.mainView;\n\n if (!currentAd || !currentAd.creative_url) {\n // If there is no ad to display, make the view take up no space.\n finalMainViewStyle.width = 0;\n finalMainViewStyle.height = 0;\n }\n\n return (\n <View style={finalMainViewStyle}>\n {currentAd && currentAd.creative_url ? (\n <WebView\n source={{\n uri: currentAd.creative_url,\n }}\n androidLayerType=\"hardware\"\n automaticallyAdjustContentInsets={false}\n style={styles.webView}\n onTouchStart={(e) => {\n this.setState({\n touchStartCoords: {\n x: e.nativeEvent.pageX,\n y: e.nativeEvent.pageY,\n },\n });\n }}\n onTouchEnd={(e) => {\n if (this.state.touchStartCoords) {\n const touchEndCoords: TouchCoordinates = {\n x: e.nativeEvent.pageX,\n y: e.nativeEvent.pageY,\n };\n\n if (\n Math.abs(\n this.state.touchStartCoords.x -\n touchEndCoords.x\n ) < this.props.xyDragDistanceAllowed &&\n Math.abs(\n this.state.touchStartCoords.y -\n touchEndCoords.y\n ) < this.props.xyDragDistanceAllowed\n ) {\n this.onAdZoneSelected(currentAd);\n }\n\n // Make sure to reset the start coords\n this.setState({\n touchStartCoords: undefined,\n });\n }\n }}\n />\n ) : undefined}\n </View>\n );\n }\n\n /**\n * Triggers when the user selects the ad zone.\n * @param currentAd - The ad currently displayed.\n */\n private onAdZoneSelected(currentAd: Ad): void {\n // Determine the \"action type\" and perform that specific action.\n if (\n currentAd.action_type === AdActionType.EXTERNAL &&\n currentAd.action_path\n ) {\n // Action Type: EXTERNAL\n Linking.openURL(currentAd.action_path).then();\n } else if (\n currentAd.action_type === AdActionType.CONTENT &&\n currentAd.payload &&\n currentAd.payload.detailed_list_items\n ) {\n safeInvoke(\n this.props.onAddToListTriggered,\n currentAd.payload.detailed_list_items\n );\n }\n\n this.triggerReportAdEvent(currentAd, ReportedEventType.INTERACTION);\n if (this.cycleAdTimer) {\n clearTimeout(this.cycleAdTimer);\n }\n this.cycleDisplayedAd();\n }\n\n /**\n * Triggered when we need to report an ad event to the API.\n * @param currentAd - The ad to send an event for.\n * @param eventType - The event type for the reported event.\n */\n private triggerReportAdEvent(\n currentAd: Ad,\n eventType: ReportedEventType\n ): void {\n // The event timestamp has to be sent as a unix timestamp.\n const currentTs = Math.round(new Date().getTime() / 1000);\n\n // Log the taken action/event with the API.\n adadaptedApiRequests\n .reportAdEvent(\n {\n app_id: this.props.appId,\n session_id: this.props.sessionId,\n udid: this.props.udid,\n events: [\n {\n ad_id: currentAd.ad_id,\n impression_id: currentAd.impression_id,\n event_type: eventType,\n created_at: currentTs,\n },\n ],\n },\n this.props.deviceOs,\n this.props.apiEnv\n )\n .then(() => {\n // Do nothing with the response for now...\n });\n }\n\n /**\n * Generates a new timer for cycling to the next ad.\n * @param timerLength - The length of time(in milliseconds) to initialize\n * the timer with.\n */\n private createAdTimer(timerLength: number): void {\n if (this.props.adZoneData.ads.length > 0) {\n this.cycleAdTimer = setTimeout(() => {\n this.cycleDisplayedAd();\n }, timerLength);\n }\n }\n\n /**\n * Cycles to the next ad to display in the current available sequence of ads.\n */\n private cycleDisplayedAd(): void {\n // Start by determining the next ad index to display.\n let nextAdIndex = 0;\n\n if (this.state.adIndexShown < this.props.adZoneData.ads.length - 1) {\n nextAdIndex = this.state.adIndexShown + 1;\n }\n\n this.setState(\n {\n adIndexShown: nextAdIndex,\n },\n () => {\n this.initializeAd();\n }\n );\n }\n\n /**\n * Performs all ad initialization tasks when a new ad is being displayed.\n */\n private initializeAd(): void {\n // Create the new timer based on the new ad index.\n this.createAdTimer(\n this.props.adZoneData.ads[this.state.adIndexShown].refresh_time *\n 1000\n );\n\n // Trigger an impression event for the ad.\n this.triggerReportAdEvent(\n this.props.adZoneData.ads[this.state.adIndexShown],\n ReportedEventType.IMPRESSION\n );\n }\n\n /**\n * Generates all component related styles.\n * @returns the styles needed for the component.\n */\n private generateStyles(): StyleDef {\n return StyleSheet.create({\n mainView: {\n width: \"100%\",\n height: \"100%\",\n },\n webView: {\n width: \"100%\",\n height: \"100%\",\n },\n });\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"names":["React","DeviceEventEmitter","Linking","StyleSheet","View","adadaptedApiRequests","AdActionType","ReportedEventType","WebView","safeInvoke","useEffect","useState","cycleAdTimer","AdZone","props","startingAdIndex","Math","floor","random","adZoneData","ads","length","adIndexShown","setAdIndexShown","touchStartCoords","setTouchStartCoords","x","y","isAdVisible","setIsAdVisibile","defaultToInvisibleAdZone","addListener","event","itemName","acknowledge","clearTimeout","removeAllListeners","startAdTimer","sendAdImpression","generateStyles","create","mainView","width","height","webView","styles","currentAd","undefined","finalMainViewStyle","creative_url","onAdZoneSelected","currentlyDisplayedAd","action_type","EXTERNAL","action_path","openURL","then","CONTENT","payload","detailed_list_items","onAddToListTriggered","cycleDisplayedAd","forEach","ad","item","product_title","triggerReportAdEvent","INTERACTION","eventType","currentTs","round","Date","getTime","reportAdEvent","app_id","appId","session_id","sessionId","udid","events","ad_id","impression_id","event_type","created_at","deviceOs","apiEnv","refreshTime","refresh_time","setTimeout","nextAdIndex","lastAd","impression_tracked","INVISIBLE_IMPRESSION","IMPRESSION","uri","e","nativeEvent","pageX","pageY","touchEndCoords","abs","xyDragDistanceAllowed"],"sources":["AdZone.tsx"],"sourcesContent":["/**\n * Component for creating an {@link AdZone}.\n * @module\n */\nimport * as React from \"react\";\nimport {\n DeviceEventEmitter,\n Linking,\n StyleSheet,\n View,\n ViewStyle,\n} from \"react-native\";\nimport * as adadaptedApiRequests from \"../api/adadaptedApiRequests\";\nimport {\n Ad,\n AdActionType,\n DetailedListItem,\n ReportedEventType,\n Zone,\n} from \"../api/adadaptedApiTypes\";\nimport { WebView } from \"react-native-webview\";\nimport { ApiEnv, DeviceOS } from \"../index\";\nimport { safeInvoke } from \"../util\";\nimport { useEffect, useState } from \"react\";\n\n/**\n * Props interface for {@link AdZone}.\n */\ninterface Props {\n /**\n * The app ID.\n */\n appId: string;\n /**\n * The session ID.\n */\n sessionId: string;\n /**\n * The UDID.\n */\n udid: string;\n /**\n * The touch sensitivity of the Ad Zone in both the X and Y directions.\n * This is used to determine the click/press sensitivity when the\n * Ad Zone is being touched by the user as a regular touch or while\n * scrolling the view. If the amount of touch \"drag\" distance in either\n * X or Y direction is less than this value, we will treat the action as\n * a click/press on the Ad Zone.\n */\n xyDragDistanceAllowed: number;\n /**\n * The device OS used for API requests.\n */\n deviceOs: DeviceOS;\n /**\n * The API environment to use when making an API request.\n */\n apiEnv: ApiEnv;\n /**\n * The ad zone data.\n */\n adZoneData: Zone;\n /**\n * Callback that gets triggered when an \"add to list\" item/items are clicked.\n * @param items - The array of items to \"add to list\".\n */\n onAddToListTriggered?(items: DetailedListItem[]): void;\n /**\n * Track the ad zone visibility in parent component.\n */\n isAdZoneVisible?: boolean;\n /**\n * Set default ad zone visibility to false.\n */\n defaultToInvisibleAdZone?: boolean;\n}\n\n/**\n * Interface for tracking \"touch\" coordinates.\n */\ninterface TouchCoordinates {\n /**\n * The X coordinate for the touch.\n */\n x: number;\n /**\n * The Y coordinate for the touch.\n */\n y: number;\n}\n\n/**\n * Defines the style typing for the component.\n */\ninterface StyleDef {\n /**\n * Styles for the main View element.\n */\n mainView: ViewStyle;\n /**\n * Styles for the WebView element.\n */\n webView: ViewStyle;\n}\n/**\n * Timer used for cycling through ads in the zone\n * based on the ad \"refresh time\" for each ad.\n */\nlet cycleAdTimer: ReturnType<typeof setTimeout> | undefined;\n\n/**\n * Creates the AdZone component.\n * @param props - properties passed to AdZone.\n * @returns an AdZone JSX Element.\n */\nexport function AdZone(props: Props): JSX.Element {\n // Generates a random number between 0 and (number of available ads - 1).\n const startingAdIndex = Math.floor(\n Math.random() * props.adZoneData.ads.length\n );\n\n /**\n * Tracks the current ad index being shown.\n */\n const [adIndexShown, setAdIndexShown] = useState(startingAdIndex);\n /**\n * Tracks the coordinates when the user started touching the Ad View.\n */\n const [touchStartCoords, setTouchStartCoords] = useState({ x: 0, y: 0 });\n /**\n * Track ad visibility (for off-screen ads).\n */\n const [isAdVisible, setIsAdVisibile] = useState(\n props.defaultToInvisibleAdZone ? false : true\n );\n\n // - Define all useEffect triggers.\n useEffect(() => {\n DeviceEventEmitter.addListener(\"visibility-event\", (event) => {\n setIsAdVisibile(event);\n });\n DeviceEventEmitter.addListener(\"acknowledge\", (itemName) => {\n acknowledge(itemName);\n });\n return () => {\n clearTimeout(cycleAdTimer);\n DeviceEventEmitter.removeAllListeners(\"visibility-event\");\n DeviceEventEmitter.removeAllListeners(\"acknowledge\");\n };\n }, []);\n\n useEffect(() => {\n startAdTimer();\n if (isAdVisible) {\n sendAdImpression();\n }\n }, [adIndexShown]);\n\n useEffect(() => {\n if (isAdVisible) {\n sendAdImpression();\n }\n }, [isAdVisible]);\n\n /**\n * Generates all component related styles.\n * @returns the styles needed for the component.\n */\n function generateStyles(): StyleDef {\n return StyleSheet.create({\n mainView: {\n width: \"100%\",\n height: \"100%\",\n },\n webView: {\n width: \"100%\",\n height: \"100%\",\n },\n });\n }\n\n // Generate the styles each render in case the ad is updated with\n // new settings that need to be reflected in the styles of the view.\n const styles = generateStyles();\n const currentAd: Ad | undefined =\n props.adZoneData.ads[adIndexShown] || undefined;\n const finalMainViewStyle = styles.mainView;\n\n if (!currentAd || !currentAd.creative_url) {\n // If there is no ad to display, make the view take up no space.\n finalMainViewStyle.width = \"0\";\n finalMainViewStyle.height = \"0\";\n }\n\n /**\n * Triggers when the user selects the ad zone.\n * @param currentlyDisplayedAd - The ad currently displayed.\n */\n function onAdZoneSelected(currentlyDisplayedAd: Ad): void {\n // Determine the \"action type\" and perform that specific action.\n if (\n currentlyDisplayedAd.action_type === AdActionType.EXTERNAL &&\n currentlyDisplayedAd.action_path\n ) {\n // Action Type: EXTERNAL\n Linking.openURL(currentlyDisplayedAd.action_path).then();\n } else if (\n currentlyDisplayedAd.action_type === AdActionType.CONTENT &&\n currentlyDisplayedAd.payload &&\n currentlyDisplayedAd.payload.detailed_list_items\n ) {\n safeInvoke(\n props.onAddToListTriggered,\n currentlyDisplayedAd.payload.detailed_list_items\n );\n }\n\n cycleDisplayedAd();\n }\n\n /**\n * Call to acknowledge ATL item(s) added to user list.\n * @param itemName - Detailed list item title from ad that was clicked.\n */\n function acknowledge(itemName: string): void {\n if (props.adZoneData.ads) {\n props.adZoneData.ads.forEach((ad) => {\n ad.payload.detailed_list_items.forEach((item) => {\n if (item.product_title === itemName) {\n triggerReportAdEvent(ad, ReportedEventType.INTERACTION);\n }\n });\n });\n }\n }\n\n /**\n * Triggered when we need to report an ad event to the API.\n * @param ad - The ad to send an event for.\n * @param eventType - The event type for the reported event.\n */\n function triggerReportAdEvent(ad: Ad, eventType: ReportedEventType): void {\n // The event timestamp has to be sent as a unix timestamp.\n const currentTs = Math.round(new Date().getTime() / 1000);\n\n // Log the taken action/event with the API.\n adadaptedApiRequests\n .reportAdEvent(\n {\n app_id: props.appId,\n session_id: props.sessionId,\n udid: props.udid,\n events: [\n {\n ad_id: ad.ad_id,\n impression_id: ad.impression_id,\n event_type: eventType,\n created_at: currentTs,\n },\n ],\n },\n props.deviceOs,\n props.apiEnv\n )\n .then(() => {\n // Do nothing with the response for now...\n });\n }\n\n /**\n * Generates a new timer for cycling to the next ad.\n */\n function startAdTimer(): void {\n clearTimeout(cycleAdTimer);\n\n if (props.adZoneData.ads.length > 0) {\n const refreshTime: number =\n props.adZoneData.ads[adIndexShown].refresh_time * 1000;\n cycleAdTimer = setTimeout(cycleDisplayedAd, refreshTime);\n }\n }\n\n /**\n * Cycles to the next ad to display in the current available sequence of ads.\n */\n function cycleDisplayedAd(): void {\n // Start by determining the next ad index to display.\n let nextAdIndex = 0;\n const lastAd = props.adZoneData.ads[adIndexShown];\n\n if (adIndexShown < props.adZoneData.ads.length - 1) {\n nextAdIndex = adIndexShown + 1;\n }\n\n if (nextAdIndex !== adIndexShown && lastAd.impression_tracked) {\n // Reset ad impression tracking status.\n lastAd.impression_tracked = false;\n } else {\n // Send invisible ad impression if ad was not visible before end of timer cycle.\n triggerReportAdEvent(\n lastAd,\n ReportedEventType.INVISIBLE_IMPRESSION\n );\n }\n\n setAdIndexShown(nextAdIndex);\n }\n\n /**\n * Send ad tracking impression.\n */\n function sendAdImpression(): void {\n const ad = props.adZoneData.ads[adIndexShown];\n\n // Trigger an impression event for the ad.\n if (!ad.impression_tracked) {\n triggerReportAdEvent(ad, ReportedEventType.IMPRESSION);\n ad.impression_tracked = true;\n }\n }\n\n // Returned JSX.\n return (\n <View style={finalMainViewStyle}>\n {currentAd && currentAd.creative_url ? (\n <WebView\n source={{\n uri: currentAd.creative_url,\n }}\n androidLayerType=\"hardware\"\n automaticallyAdjustContentInsets={false}\n style={styles.webView}\n onTouchStart={(e) => {\n setTouchStartCoords({\n x: e.nativeEvent.pageX,\n y: e.nativeEvent.pageY,\n });\n }}\n onTouchEnd={(e) => {\n if (touchStartCoords) {\n const touchEndCoords: TouchCoordinates = {\n x: e.nativeEvent.pageX,\n y: e.nativeEvent.pageY,\n };\n\n if (\n Math.abs(\n touchStartCoords.x - touchEndCoords.x\n ) < props.xyDragDistanceAllowed &&\n Math.abs(\n touchStartCoords.y - touchEndCoords.y\n ) < props.xyDragDistanceAllowed\n ) {\n onAdZoneSelected(currentAd);\n }\n\n // Make sure to reset the start coords\n setTouchStartCoords({ x: 0, y: 0 });\n }\n }}\n />\n ) : undefined}\n </View>\n );\n}\n"],"mappings":"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"}
@@ -3,7 +3,7 @@ function _defineProperty(obj, key, value) { if (key in obj) { Object.definePrope
3
3
  * The AdadaptedReactNativeSdk package/module definition.
4
4
  */
5
5
  import * as React from "react";
6
- import { AppState, Linking, NativeModules, Platform } from "react-native";
6
+ import { AppState, DeviceEventEmitter, Linking, NativeModules, Platform } from "react-native";
7
7
  import * as adadaptedApiRequests from "./api/adadaptedApiRequests";
8
8
  import { ListManagerEventName, ListManagerEventSource, PayloadStatus, ReportedEventType } from "./api/adadaptedApiTypes";
9
9
  import { AdZone } from "./components/AdZone";
@@ -146,6 +146,14 @@ export class AdadaptedReactNativeSdk {
146
146
  * AppState event listener.
147
147
  */
148
148
 
149
+ /**
150
+ * Track ad zone visibility for off-screen ads.
151
+ */
152
+
153
+ /**
154
+ * Optional default ad zone visibility for off-screen ads.
155
+ */
156
+
149
157
  /**
150
158
  * Gets the Session ID.
151
159
  * @returns the Session ID.
@@ -192,6 +200,8 @@ export class AdadaptedReactNativeSdk {
192
200
  _defineProperty(this, "onOutOfAppPayloadAvailable", void 0);
193
201
  _defineProperty(this, "deepLinkOnEventListener", void 0);
194
202
  _defineProperty(this, "AppStateOnEventListener", void 0);
203
+ _defineProperty(this, "isAdZoneVisible", true);
204
+ _defineProperty(this, "defaultAdZoneVisibility", void 0);
195
205
  this.apiEnv = ApiEnv.Prod;
196
206
  this.listManagerApiEnv = ListManagerApiEnv.Prod;
197
207
  this.payloadApiEnv = PayloadApiEnv.Prod;
@@ -245,7 +255,9 @@ export class AdadaptedReactNativeSdk {
245
255
  adZoneData: adZones[adZoneId],
246
256
  onAddToListTriggered: items => {
247
257
  safeInvoke(this.onAddToListTriggered, items);
248
- }
258
+ },
259
+ isAdZoneVisible: !this.onAdZoneVisibilityChanged,
260
+ defaultToInvisibleAdZone: this.defaultAdZoneVisibility
249
261
  })
250
262
  });
251
263
  }
@@ -298,7 +310,6 @@ export class AdadaptedReactNativeSdk {
298
310
  uid: this.deviceInfo.udid
299
311
  }, this.deviceOs, this.apiEnv).then(response => {
300
312
  this.keywordIntercepts = response.data;
301
- this.performKeywordSearch("mil");
302
313
  });
303
314
  }
304
315
 
@@ -436,6 +447,23 @@ export class AdadaptedReactNativeSdk {
436
447
  });
437
448
  }
438
449
 
450
+ /**
451
+ * Notify the ad zone of visibility status change for off-screen ads.
452
+ */
453
+ onAdZoneVisibilityChanged() {
454
+ const isVisible = !this.isAdZoneVisible;
455
+ this.isAdZoneVisible = isVisible;
456
+ DeviceEventEmitter.emit("visibility-event", isVisible);
457
+ }
458
+
459
+ /**
460
+ * Notify the adZone to send ad interaction report.
461
+ * @param itemName - Detailed list item title from ad that was clicked.
462
+ */
463
+ acknowledge(itemName) {
464
+ DeviceEventEmitter.emit("acknowledge", itemName);
465
+ }
466
+
439
467
  /**
440
468
  * Initializes the session for the AdAdapted API and sets up the SDK.
441
469
  * @param props - The props used to initialize the SDK.
@@ -487,6 +515,12 @@ export class AdadaptedReactNativeSdk {
487
515
  if (props.onOutOfAppPayloadAvailable) {
488
516
  this.onOutOfAppPayloadAvailable = props.onOutOfAppPayloadAvailable;
489
517
  }
518
+
519
+ // If provided for off-screen ads, set the ad zone visibility for ad tracking.
520
+ if (props.defaultToInvisibleAdZone) {
521
+ this.defaultAdZoneVisibility = props.defaultToInvisibleAdZone;
522
+ this.onAdZoneVisibilityChanged();
523
+ }
490
524
  return new Promise((resolve, reject) => {
491
525
  this.getDeviceInformation().then(deviceInfoObj => {
492
526
  const deviceInfo = JSON.parse(deviceInfoObj);