react-native-test-adx 0.1.6 → 0.1.8

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,8 +1,8 @@
1
1
  "use strict";
2
2
 
3
3
  import { AdaxonClient } from "./core/AdaxonClient.js";
4
- import { MEDIATION_PROVIDER, OFFER_OPENED_EVENT, RECOMMENDATION_VIEW_EVENT } from "./config/ApiConstants.js";
5
- import { dismissInterstitial, presentInterstitial } from "./components/InterstitialAd.js";
4
+ import { CREATIVE_CLICK_EVENT, CREATIVE_VIEW_EVENT, MEDIATION_PROVIDER, RECOMMENDATION_EVENT_TYPE } from "./config/ApiConstants.js";
5
+ import { dismissInterstitial, dismissOfferBrowser, presentInterstitial, presentOfferBrowser } from "./components/InterstitialAd.js";
6
6
  import { AdaxonSdkError } from "./errors/AdaxonSdkError.js";
7
7
  import { detectReactNativePlatform, reactNativeAppInfoReader, reactNativeDeviceReader, reactNativeNetworkInfoReader, reactNativeNetworkStatusReader, reactNativeUrlOpener } from "./platform/reactNative.js";
8
8
  import { buildAddToCartProperties, buildPurchaseProperties, normalizeEventValues } from "./services/event/normalizeProperties.js";
@@ -70,7 +70,10 @@ export class AdaxonSdk {
70
70
  }
71
71
  async showAd(options = {}) {
72
72
  try {
73
- const offers = await this.loadRecommendations(RECOMMENDATION_VIEW_EVENT);
73
+ const {
74
+ offers,
75
+ requestEventId
76
+ } = await this.loadRecommendations();
74
77
  if (offers.length === 0) {
75
78
  console.warn('[Adaxon] No offer available.');
76
79
  return {
@@ -91,10 +94,8 @@ export class AdaxonSdk {
91
94
  const displayed = presentInterstitial({
92
95
  offer,
93
96
  interact: () => {
94
- options.onOfferClicked?.(offer.offer_id);
95
- this.openOfferUrl(offer).then(() => dismissInterstitial('click')).catch(error => {
97
+ this.openOfferUrl(offer, requestEventId).then(() => options.onOfferClicked?.(offer.offer_id)).catch(error => {
96
98
  console.warn('[Adaxon] Failed to open offer URL.', AdaxonSdkError.messageOf(error, 'Failed to open offer.'));
97
- dismissInterstitial('close');
98
99
  });
99
100
  },
100
101
  onDismiss: dismissReason => {
@@ -111,7 +112,9 @@ export class AdaxonSdk {
111
112
  shown: false,
112
113
  reason: 'not_mounted'
113
114
  });
115
+ return;
114
116
  }
117
+ this.trackRecommendationEvent(CREATIVE_VIEW_EVENT, requestEventId).catch(() => undefined);
115
118
  });
116
119
  } catch (error) {
117
120
  console.warn('[Adaxon] Failed to show ad.', AdaxonSdkError.messageOf(error, 'Failed to show ad.'));
@@ -129,33 +132,35 @@ export class AdaxonSdk {
129
132
  }
130
133
  destroy() {
131
134
  dismissInterstitial();
135
+ dismissOfferBrowser();
132
136
  this.client?.destroy();
133
137
  this.client = null;
134
138
  this.testMode = false;
135
139
  }
136
- async loadRecommendations(eventName, properties = {}) {
137
- const response = await this.requireClient().getRecommendations({
138
- eventName,
139
- properties: {
140
- ...properties,
141
- mediation_provider: MEDIATION_PROVIDER,
142
- test_mode: this.testMode
143
- }
140
+ loadRecommendations() {
141
+ return this.requireClient().getRecommendations({
142
+ mediation_provider: MEDIATION_PROVIDER,
143
+ test_mode: this.testMode
144
144
  });
145
- return response.offers;
146
145
  }
147
- async openOfferUrl(offer) {
148
- const client = this.requireClient();
149
- if (!(await reactNativeUrlOpener.canOpenURL(offer.offer_url))) {
150
- throw new AdaxonSdkError('VALIDATION_ERROR', `Cannot open offer URL: ${offer.offer_url}`);
146
+ async openOfferUrl(offer, parentEventId) {
147
+ await this.trackRecommendationEvent(CREATIVE_CLICK_EVENT, parentEventId);
148
+ if (presentOfferBrowser(offer.offer_url)) {
149
+ return;
151
150
  }
152
151
  await reactNativeUrlOpener.openURL(offer.offer_url);
153
- await client.track(OFFER_OPENED_EVENT, {
154
- offer_id: offer.offer_id,
155
- offer_name: offer.offer_name,
156
- ad_type: offer.ad_type,
157
- mediation_provider: MEDIATION_PROVIDER
158
- });
152
+ dismissInterstitial('click');
153
+ }
154
+ async trackRecommendationEvent(eventName, parentEventId) {
155
+ try {
156
+ await this.requireClient().track(eventName, {
157
+ parent_event_id: parentEventId
158
+ }, {
159
+ eventType: RECOMMENDATION_EVENT_TYPE
160
+ });
161
+ } catch (error) {
162
+ console.warn(`[Adaxon] Failed to log ${eventName}.`, AdaxonSdkError.messageOf(error, `Failed to log ${eventName}.`));
163
+ }
159
164
  }
160
165
  requireClient() {
161
166
  if (!this.client) {
@@ -1,12 +1,35 @@
1
1
  "use strict";
2
2
 
3
3
  import { useEffect, useState } from 'react';
4
- import { BackHandler, Image, Platform, Pressable, SafeAreaView, StatusBar, StyleSheet, Text, View } from "../platform/reactNative.js";
4
+ import { BackHandler, Image, Platform, Pressable, SafeAreaView, StatusBar, StyleSheet, Text, View, reactNativeUrlOpener } from "../platform/reactNative.js";
5
5
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
6
6
  const CLOSE_EDGE_INSET = 12;
7
7
  const CLOSE_HIT_SIZE = 44;
8
+ function loadInAppBrowser() {
9
+ try {
10
+ const module = require('react-native-webview');
11
+ return module.WebView ?? null;
12
+ } catch {
13
+ return null;
14
+ }
15
+ }
16
+ const InAppBrowserView = loadInAppBrowser();
8
17
  let listener = null;
9
18
  let activeSession = null;
19
+ let browserListener = null;
20
+ let activeBrowserUrl = null;
21
+ export function presentOfferBrowser(url) {
22
+ if (!browserListener || !InAppBrowserView) {
23
+ return false;
24
+ }
25
+ activeBrowserUrl = url;
26
+ browserListener(url);
27
+ return true;
28
+ }
29
+ export function dismissOfferBrowser() {
30
+ activeBrowserUrl = null;
31
+ browserListener?.(null);
32
+ }
10
33
  export function presentInterstitial(session) {
11
34
  if (!listener) {
12
35
  return false;
@@ -51,83 +74,137 @@ function useTopInset() {
51
74
  }
52
75
  export function InterstitialAd() {
53
76
  const [session, setSession] = useState(null);
77
+ const [browserUrl, setBrowserUrl] = useState(null);
78
+ const [offerPageVisible, setOfferPageVisible] = useState(false);
54
79
  const [closeTone, setCloseTone] = useState('onLightSurface');
55
80
  const safeArea = useSafeAreaInsets();
56
81
  const topInset = useTopInset();
57
82
  const offerId = session?.offer.offer_id;
58
83
  useEffect(() => {
59
84
  listener = setSession;
85
+ browserListener = setBrowserUrl;
86
+ setBrowserUrl(activeBrowserUrl);
60
87
  return () => {
61
88
  if (listener === setSession) {
62
89
  listener = null;
63
90
  }
91
+ if (browserListener === setBrowserUrl) {
92
+ browserListener = null;
93
+ }
64
94
  };
65
95
  }, []);
66
96
  useEffect(() => {
67
97
  setCloseTone('onLightSurface');
68
98
  }, [offerId]);
69
99
  useEffect(() => {
70
- if (!session) {
100
+ setOfferPageVisible(false);
101
+ }, [browserUrl]);
102
+ useEffect(() => {
103
+ if (!session && !browserUrl) {
71
104
  return;
72
105
  }
73
106
  const onBackPress = () => {
74
- dismissInterstitial('back');
107
+ dismissOfferBrowser();
108
+ if (session && !offerPageVisible) {
109
+ dismissInterstitial('back');
110
+ }
75
111
  return true;
76
112
  };
77
113
  const subscription = BackHandler.addEventListener('hardwareBackPress', onBackPress);
78
114
  return () => subscription.remove();
79
- }, [session]);
80
- if (!session) {
115
+ }, [browserUrl, offerPageVisible, session]);
116
+ if (!session && !browserUrl) {
81
117
  return null;
82
118
  }
83
- const {
84
- offer,
85
- interact
86
- } = session;
87
119
  const closeAppearance = closeButtonAppearance(closeTone);
88
120
  const closeRightInset = Platform.OS === 'android' ? CLOSE_EDGE_INSET + safeArea.right : CLOSE_EDGE_INSET;
89
- const adFrame = /*#__PURE__*/_jsx(_Fragment, {
90
- children: /*#__PURE__*/_jsxs(View, {
91
- style: styles.adContainer,
92
- children: [/*#__PURE__*/_jsx(Pressable, {
93
- accessibilityRole: "button",
94
- accessibilityLabel: "Close ad",
95
- onPress: () => dismissInterstitial('close'),
96
- style: [styles.closeButton, closeAppearance.button, {
97
- top: CLOSE_EDGE_INSET,
98
- right: closeRightInset
99
- }],
100
- testID: "adaxon-interstitial-close",
101
- children: /*#__PURE__*/_jsx(Text, {
102
- style: [styles.closeLabel, closeAppearance.label],
103
- children: "\xD7"
104
- })
105
- }), /*#__PURE__*/_jsx(Pressable, {
106
- accessibilityRole: "button",
107
- accessibilityLabel: offer.offer_name,
108
- onPress: interact,
109
- style: styles.offer,
110
- testID: "adaxon-interstitial-offer",
111
- children: /*#__PURE__*/_jsx(OfferCreative, {
112
- offer: offer,
113
- onCloseToneChange: setCloseTone
114
- })
115
- })]
121
+ const closeButton = (label, onPress, testID) => /*#__PURE__*/_jsx(Pressable, {
122
+ accessibilityRole: "button",
123
+ accessibilityLabel: label,
124
+ onPress: onPress,
125
+ style: [styles.closeButton, closeAppearance.button, {
126
+ top: CLOSE_EDGE_INSET,
127
+ right: closeRightInset
128
+ }],
129
+ testID: testID,
130
+ children: /*#__PURE__*/_jsx(Text, {
131
+ style: [styles.closeLabel, closeAppearance.label],
132
+ children: "\xD7"
116
133
  })
117
134
  });
118
- return /*#__PURE__*/_jsx(View, {
119
- style: styles.overlay,
120
- testID: "adaxon-interstitial",
121
- children: Platform.OS === 'ios' ? /*#__PURE__*/_jsx(SafeAreaView, {
122
- style: styles.safeFrame,
123
- children: adFrame
124
- }) : /*#__PURE__*/_jsx(View, {
135
+ const adFrame = session ? /*#__PURE__*/_jsxs(View, {
136
+ style: styles.adContainer,
137
+ children: [/*#__PURE__*/_jsx(Pressable, {
138
+ accessibilityRole: "button",
139
+ accessibilityLabel: session.offer.offer_name,
140
+ onPress: session.interact,
141
+ style: styles.offer,
142
+ testID: "adaxon-interstitial-offer",
143
+ children: /*#__PURE__*/_jsx(OfferCreative, {
144
+ offer: session.offer,
145
+ onCloseToneChange: setCloseTone
146
+ })
147
+ }), closeButton('Close ad', () => {
148
+ dismissOfferBrowser();
149
+ dismissInterstitial('close');
150
+ }, 'adaxon-interstitial-close')]
151
+ }) : null;
152
+ const onOfferNavigation = request => {
153
+ const externalUrl = externalAppUrl(request.url);
154
+ if (!externalUrl) {
155
+ return true;
156
+ }
157
+ reactNativeUrlOpener.openURL(externalUrl).catch(() => undefined);
158
+ dismissOfferBrowser();
159
+ dismissInterstitial('click');
160
+ return false;
161
+ };
162
+ const onOfferPage = state => {
163
+ if (state.loading || !state.url || !browserUrl) {
164
+ return;
165
+ }
166
+ setOfferPageVisible(true);
167
+ dismissInterstitial('click');
168
+ };
169
+ const offerBrowser = InAppBrowserView && browserUrl ? /*#__PURE__*/_jsx(InAppBrowserView, {
170
+ source: {
171
+ uri: browserUrl
172
+ },
173
+ pointerEvents: offerPageVisible ? 'auto' : 'none',
174
+ style: offerPageVisible ? styles.browser : styles.hiddenBrowser,
175
+ originWhitelist: ['*'],
176
+ onShouldStartLoadWithRequest: onOfferNavigation,
177
+ onNavigationStateChange: onOfferPage,
178
+ testID: "adaxon-interstitial-browser"
179
+ }) : null;
180
+ return /*#__PURE__*/_jsxs(_Fragment, {
181
+ children: [offerBrowser && !offerPageVisible ? offerBrowser : null, session ? /*#__PURE__*/_jsx(View, {
182
+ style: styles.overlay,
183
+ testID: "adaxon-interstitial",
184
+ children: framed(adFrame)
185
+ }) : null, offerBrowser && offerPageVisible ? /*#__PURE__*/_jsx(View, {
186
+ style: styles.overlay,
187
+ testID: "adaxon-offer-browser",
188
+ children: framed(/*#__PURE__*/_jsxs(View, {
189
+ style: styles.adContainer,
190
+ children: [offerBrowser, closeButton('Close offer', dismissOfferBrowser, 'adaxon-offer-close')]
191
+ }))
192
+ }) : null]
193
+ });
194
+ function framed(content) {
195
+ if (Platform.OS === 'ios') {
196
+ return /*#__PURE__*/_jsx(SafeAreaView, {
197
+ style: styles.safeFrame,
198
+ children: content
199
+ });
200
+ }
201
+ return /*#__PURE__*/_jsx(View, {
125
202
  style: [styles.safeFrame, {
126
203
  paddingTop: topInset
127
204
  }],
128
- children: adFrame
129
- })
130
- });
205
+ children: content
206
+ });
207
+ }
131
208
  }
132
209
  function OfferCreative({
133
210
  offer,
@@ -191,6 +268,37 @@ function closeButtonAppearance(tone) {
191
268
  }
192
269
  };
193
270
  }
271
+ function externalAppUrl(url) {
272
+ const trimmed = url.trim();
273
+ if (!trimmed || trimmed === 'about:blank') {
274
+ return null;
275
+ }
276
+ let protocol = '';
277
+ try {
278
+ protocol = new URL(trimmed).protocol;
279
+ } catch {
280
+ return null;
281
+ }
282
+ if (protocol === 'http:' || protocol === 'https:' || protocol === 'about:' || protocol === 'blob:' || protocol === 'data:') {
283
+ return null;
284
+ }
285
+ if (protocol === 'intent:') {
286
+ return intentTarget(trimmed);
287
+ }
288
+ return trimmed;
289
+ }
290
+ function intentTarget(url) {
291
+ const fallback = /S\.browser_fallback_url=([^;]+)/.exec(url)?.[1];
292
+ if (fallback) {
293
+ return decodeURIComponent(fallback);
294
+ }
295
+ const scheme = /scheme=([^;]+)/.exec(url)?.[1];
296
+ const path = url.slice('intent:'.length).split('#')[0];
297
+ if (!scheme || !path) {
298
+ return url;
299
+ }
300
+ return `${scheme}:${path}`;
301
+ }
194
302
  function remoteImageUrl(value) {
195
303
  const trimmed = value?.trim();
196
304
  if (!trimmed) {
@@ -260,6 +368,20 @@ const styles = StyleSheet.create({
260
368
  alignSelf: 'stretch',
261
369
  overflow: 'hidden'
262
370
  },
371
+ browser: {
372
+ flex: 1,
373
+ width: '100%',
374
+ backgroundColor: '#ffffff'
375
+ },
376
+ hiddenBrowser: {
377
+ position: 'absolute',
378
+ top: 0,
379
+ right: 0,
380
+ bottom: 0,
381
+ left: 0,
382
+ opacity: 0,
383
+ zIndex: 0
384
+ },
263
385
  creativeImage: {
264
386
  position: 'absolute',
265
387
  top: 0,
@@ -8,8 +8,11 @@ export const BASE_URL = 'https://mts-tracking.mobupps.com';
8
8
  export const EVENT_TRACKING_PATH = '/event/tracking';
9
9
  export const RECOMMENDATIONS_PATH = '/api/mts/recommendations';
10
10
  export const CLICK_TRACKING_PATH = '/click/tracking';
11
- export const OFFER_OPENED_EVENT = 'offer_opened';
12
- export const RECOMMENDATION_VIEW_EVENT = 'recommendation_view';
11
+ export const RECOMMENDATION_EVENT_TYPE = 'recommendation';
12
+ export const RECOMMENDATION_REQUEST_EVENT = 'recommendation_request';
13
+ export const RECOMMENDATION_RESPONSE_EVENT = 'recommendation_response';
14
+ export const CREATIVE_VIEW_EVENT = 'creative_view';
15
+ export const CREATIVE_CLICK_EVENT = 'creative_click';
13
16
  export const DEFAULT_TIMEOUT_MS = 10_000;
14
17
  export const PUBLIC_IP_LOOKUP_URL = 'https://api.ipify.org?format=json';
15
18
  export const PUBLIC_IP_LOOKUP_TIMEOUT_MS = 2_000;
@@ -95,8 +95,8 @@ export class AdaxonClient {
95
95
  processPendingEvents() {
96
96
  return this.batchProcessor.process();
97
97
  }
98
- getRecommendations(input) {
99
- return this.events.getRecommendations(input);
98
+ getRecommendations(properties = {}) {
99
+ return this.events.getRecommendations(properties);
100
100
  }
101
101
  createClickUrl(attribution) {
102
102
  this.validator.validateClickAttribution(attribution);
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
 
3
3
  import { AdaxonSdk } from "./AdaxonSdk.js";
4
+ export { BASE_URL } from "./config/ApiConstants.js";
4
5
  export { AdaxonProvider } from "./components/AdaxonProvider.js";
5
6
  export { useAdaxon } from "./hooks/useAdaxon.js";
6
7
  export { AdaxonSdk };
@@ -1,4 +1,4 @@
1
1
  "use strict";
2
2
 
3
3
  /** Keep in sync with package.json "version" (published npm packages ship lib/ only). */
4
- export const SDK_VERSION = '0.1.6';
4
+ export const SDK_VERSION = '0.1.8';
@@ -18,7 +18,7 @@ export class EventBuilder {
18
18
  const user = {
19
19
  anonymous_id: await deviceInfo.getUniqueId()
20
20
  };
21
- return {
21
+ const payload = {
22
22
  event_id: input.eventId ?? createUuid(),
23
23
  event_name: input.eventName,
24
24
  event_time: input.eventTime ?? new Date().toISOString(),
@@ -32,5 +32,9 @@ export class EventBuilder {
32
32
  },
33
33
  network: await networkInfo.getNetworkInfo()
34
34
  };
35
+ if (input.eventType) {
36
+ payload.event_type = input.eventType;
37
+ }
38
+ return payload;
35
39
  }
36
40
  }
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
 
3
- import { EVENT_TRACKING_PATH, RECOMMENDATIONS_PATH } from "../../config/ApiConstants.js";
3
+ import { EVENT_TRACKING_PATH, RECOMMENDATION_EVENT_TYPE, RECOMMENDATION_REQUEST_EVENT, RECOMMENDATION_RESPONSE_EVENT, RECOMMENDATIONS_PATH } from "../../config/ApiConstants.js";
4
4
  import { AdaxonSdkError } from "../../errors/AdaxonSdkError.js";
5
5
  export class EventService {
6
6
  constructor(config) {
@@ -17,19 +17,33 @@ export class EventService {
17
17
  this.validator.validateBatch(payloads);
18
18
  return this.postEvents(payloads);
19
19
  }
20
- async getRecommendations(input) {
21
- const eventPayload = await this.builder.build(input);
22
- await this.postEvents([eventPayload]);
20
+ async getRecommendations(properties = {}) {
21
+ const requestEvent = await this.builder.build({
22
+ eventName: RECOMMENDATION_REQUEST_EVENT,
23
+ eventType: RECOMMENDATION_EVENT_TYPE,
24
+ properties
25
+ });
26
+ await this.postEvents([requestEvent]);
23
27
  const response = await this.api.post(RECOMMENDATIONS_PATH, {
24
- app_id: eventPayload.app_id,
28
+ app_id: requestEvent.app_id,
25
29
  device: {
26
- platform: eventPayload.device.platform
30
+ platform: requestEvent.device.platform
27
31
  }
28
32
  });
29
33
  if (!Array.isArray(response.offers)) {
30
34
  throw new AdaxonSdkError('HTTP_ERROR', 'Adaxon recommendation response is missing the offers array.');
31
35
  }
32
- return response;
36
+ await this.postEvents([await this.builder.build({
37
+ eventName: RECOMMENDATION_RESPONSE_EVENT,
38
+ eventType: RECOMMENDATION_EVENT_TYPE,
39
+ properties: {
40
+ parent_event_id: requestEvent.event_id
41
+ }
42
+ })]);
43
+ return {
44
+ offers: response.offers,
45
+ requestEventId: requestEvent.event_id
46
+ };
33
47
  }
34
48
  postEvents(payloads) {
35
49
  return this.api.post(EVENT_TRACKING_PATH, payloads);
@@ -12,6 +12,9 @@ export class EventValidator {
12
12
  }
13
13
  validateTrackInput(input) {
14
14
  this.validateEventName(input.eventName);
15
+ if (input.eventType) {
16
+ this.validateEventName(input.eventType, 'eventType');
17
+ }
15
18
  this.validateProperties(input.properties ?? {});
16
19
  if (input.eventId && !UUID_PATTERN.test(input.eventId)) {
17
20
  this.fail('eventId must be a valid UUID.');
@@ -20,9 +23,9 @@ export class EventValidator {
20
23
  this.fail('eventTime must be a valid ISO 8601 datetime string.');
21
24
  }
22
25
  }
23
- validateEventName(eventName) {
26
+ validateEventName(eventName, label = 'eventName') {
24
27
  if (!eventName || eventName.length > MAX_EVENT_NAME_LENGTH || !EVENT_NAME_PATTERN.test(eventName)) {
25
- this.fail(`eventName must start with a letter, contain only letters, numbers, and underscores, and be at most ${MAX_EVENT_NAME_LENGTH} characters.`);
28
+ this.fail(`${label} must start with a letter, contain only letters, numbers, and underscores, and be at most ${MAX_EVENT_NAME_LENGTH} characters.`);
26
29
  }
27
30
  }
28
31
  validateProperties(properties) {
@@ -37,6 +37,7 @@ export declare class AdaxonSdk {
37
37
  destroy(): void;
38
38
  private loadRecommendations;
39
39
  private openOfferUrl;
40
+ private trackRecommendationEvent;
40
41
  private requireClient;
41
42
  }
42
43
  //# sourceMappingURL=AdaxonSdk.d.ts.map
@@ -5,6 +5,8 @@ export interface InterstitialAdSession {
5
5
  interact: () => void;
6
6
  onDismiss?: (reason: InterstitialDismissReason) => void;
7
7
  }
8
+ export declare function presentOfferBrowser(url: string): boolean;
9
+ export declare function dismissOfferBrowser(): void;
8
10
  export declare function presentInterstitial(session: InterstitialAdSession): boolean;
9
11
  export declare function dismissInterstitial(reason?: InterstitialDismissReason): void;
10
12
  export declare function InterstitialAd(): import("react").JSX.Element | null;
@@ -4,8 +4,11 @@ export declare const BASE_URL = "https://mts-tracking.mobupps.com";
4
4
  export declare const EVENT_TRACKING_PATH = "/event/tracking";
5
5
  export declare const RECOMMENDATIONS_PATH = "/api/mts/recommendations";
6
6
  export declare const CLICK_TRACKING_PATH = "/click/tracking";
7
- export declare const OFFER_OPENED_EVENT = "offer_opened";
8
- export declare const RECOMMENDATION_VIEW_EVENT = "recommendation_view";
7
+ export declare const RECOMMENDATION_EVENT_TYPE = "recommendation";
8
+ export declare const RECOMMENDATION_REQUEST_EVENT = "recommendation_request";
9
+ export declare const RECOMMENDATION_RESPONSE_EVENT = "recommendation_response";
10
+ export declare const CREATIVE_VIEW_EVENT = "creative_view";
11
+ export declare const CREATIVE_CLICK_EVENT = "creative_click";
9
12
  export declare const DEFAULT_TIMEOUT_MS = 10000;
10
13
  export declare const PUBLIC_IP_LOOKUP_URL = "https://api.ipify.org?format=json";
11
14
  export declare const PUBLIC_IP_LOOKUP_TIMEOUT_MS = 2000;
@@ -1,6 +1,6 @@
1
1
  import type { AppInfoReader, DeviceInfoReader, NetworkInfoReader, NetworkStatusReader } from '../platform/types.js';
2
2
  import type { AdaxonSdkConfig } from '../types/AdaxonConfig.js';
3
- import type { EventIngestionResponse, RecommendationResponse } from '../types/ApiTypes.js';
3
+ import type { EventIngestionResponse, RecommendationFlowResult } from '../types/ApiTypes.js';
4
4
  import type { AdaxonPlatform, ClickAttribution, EventProperties, TrackEventInput, TrackEventOptions } from '../types/EventTypes.js';
5
5
  import type { BatchProcessResult } from '../types/QueuedEvent.js';
6
6
  interface AdaxonClientConfig extends AdaxonSdkConfig {
@@ -26,7 +26,7 @@ export declare class AdaxonClient {
26
26
  trackBatch(events: readonly TrackEventInput[]): Promise<EventIngestionResponse>;
27
27
  enqueueEvent(eventName: string, properties?: EventProperties, options?: TrackEventOptions): Promise<void>;
28
28
  processPendingEvents(): Promise<BatchProcessResult>;
29
- getRecommendations(input: TrackEventInput): Promise<RecommendationResponse>;
29
+ getRecommendations(properties?: EventProperties): Promise<RecommendationFlowResult>;
30
30
  createClickUrl(attribution: ClickAttribution): string;
31
31
  private toQueryString;
32
32
  }
@@ -1,4 +1,5 @@
1
1
  import { AdaxonSdk } from './AdaxonSdk.js';
2
+ export { BASE_URL } from './config/ApiConstants.js';
2
3
  export { AdaxonProvider } from './components/AdaxonProvider.js';
3
4
  export type { AdaxonProviderProps } from './components/AdaxonProvider.js';
4
5
  export { useAdaxon } from './hooks/useAdaxon.js';
@@ -1,3 +1,3 @@
1
1
  /** Keep in sync with package.json "version" (published npm packages ship lib/ only). */
2
- export declare const SDK_VERSION = "0.1.6";
2
+ export declare const SDK_VERSION = "0.1.8";
3
3
  //# sourceMappingURL=sdkVersion.d.ts.map
@@ -1,6 +1,6 @@
1
1
  import type { ApiClient } from '../network/ApiClient.js';
2
- import type { EventIngestionResponse, RecommendationResponse } from '../../types/ApiTypes.js';
3
- import type { EventPayload, TrackEventInput } from '../../types/EventTypes.js';
2
+ import type { EventIngestionResponse, RecommendationFlowResult } from '../../types/ApiTypes.js';
3
+ import type { EventPayload, EventProperties, TrackEventInput } from '../../types/EventTypes.js';
4
4
  import type { EventBuilder } from './EventBuilder.js';
5
5
  import type { EventValidator } from '../../validation/EventValidator.js';
6
6
  interface EventServiceConfig {
@@ -15,7 +15,7 @@ export declare class EventService {
15
15
  constructor(config: EventServiceConfig);
16
16
  trackBatch(events: readonly TrackEventInput[]): Promise<EventIngestionResponse>;
17
17
  sendPayloads(payloads: readonly EventPayload[]): Promise<EventIngestionResponse>;
18
- getRecommendations(input: TrackEventInput): Promise<RecommendationResponse>;
18
+ getRecommendations(properties?: EventProperties): Promise<RecommendationFlowResult>;
19
19
  private postEvents;
20
20
  }
21
21
  export {};
@@ -23,6 +23,10 @@ export interface RecommendationOffer {
23
23
  export interface RecommendationResponse {
24
24
  offers: RecommendationOffer[];
25
25
  }
26
+ export interface RecommendationFlowResult {
27
+ offers: RecommendationOffer[];
28
+ requestEventId: string;
29
+ }
26
30
  export interface AdaxonApiErrorBody {
27
31
  success?: boolean;
28
32
  message?: string;
@@ -32,11 +32,13 @@ export interface TrackEventInput {
32
32
  properties?: EventProperties;
33
33
  eventId?: string;
34
34
  eventTime?: string;
35
+ eventType?: string;
35
36
  }
36
37
  export type TrackEventOptions = Omit<TrackEventInput, 'eventName' | 'properties'>;
37
38
  export interface EventPayload {
38
39
  event_id: string;
39
40
  event_name: string;
41
+ event_type?: string;
40
42
  event_time: string;
41
43
  app_id: string;
42
44
  properties: EventProperties;
@@ -4,7 +4,7 @@ export declare class EventValidator {
4
4
  readonly length: number;
5
5
  }): void;
6
6
  validateTrackInput(input: TrackEventInput): void;
7
- validateEventName(eventName: string): void;
7
+ validateEventName(eventName: string, label?: string): void;
8
8
  validateProperties(properties: EventProperties): void;
9
9
  validateClickAttribution(attribution: ClickAttribution): void;
10
10
  private validatePositiveInteger;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-test-adx",
3
- "version": "0.1.6",
3
+ "version": "0.1.8",
4
4
  "description": "Adaxon React Native / Expo SDK for event tracking and offer recommendations.",
5
5
  "main": "./lib/module/index.js",
6
6
  "types": "./lib/typescript/src/index.d.ts",