@ezoic/react-native-sdk 1.3.0 → 1.4.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.
- package/EzoicReactNativeSdk.podspec +1 -1
- package/README.md +63 -3
- package/android/build.gradle +1 -1
- package/android/src/main/java/com/ezoic/reactnative/EzoicAdsModule.kt +129 -0
- package/android/src/main/java/com/ezoic/reactnative/EzoicOutstreamAdViewManager.kt +191 -0
- package/android/src/main/java/com/ezoic/reactnative/EzoicReactNativeSdkPackage.kt +2 -1
- package/ios/EzoicAdsImpl.swift +160 -0
- package/ios/EzoicOutstreamAdHostView.swift +86 -0
- package/ios/EzoicOutstreamAdViewComponentView.mm +105 -0
- package/ios/EzoicReactNativeSdk.mm +41 -0
- package/lib/module/EzoicInstreamAd.js +91 -0
- package/lib/module/EzoicInstreamAd.js.map +1 -0
- package/lib/module/EzoicOutstreamAdViewNativeComponent.ts +23 -0
- package/lib/module/NativeEzoicAds.js.map +1 -1
- package/lib/module/index.js +30 -0
- package/lib/module/index.js.map +1 -1
- package/lib/typescript/src/EzoicInstreamAd.d.ts +86 -0
- package/lib/typescript/src/EzoicInstreamAd.d.ts.map +1 -0
- package/lib/typescript/src/EzoicOutstreamAdViewNativeComponent.d.ts +18 -0
- package/lib/typescript/src/EzoicOutstreamAdViewNativeComponent.d.ts.map +1 -0
- package/lib/typescript/src/NativeEzoicAds.d.ts +4 -0
- package/lib/typescript/src/NativeEzoicAds.d.ts.map +1 -1
- package/lib/typescript/src/index.d.ts +22 -0
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/EzoicInstreamAd.ts +110 -0
- package/src/EzoicOutstreamAdViewNativeComponent.ts +23 -0
- package/src/NativeEzoicAds.ts +18 -0
- package/src/index.tsx +53 -0
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import NativeEzoicAds from './NativeEzoicAds';
|
|
2
|
+
|
|
3
|
+
/** Options for {@link EzoicInstreamAd.load}. */
|
|
4
|
+
export interface EzoicInstreamLoadOptions {
|
|
5
|
+
/**
|
|
6
|
+
* The URL of the video the host is currently playing. When supplied it is
|
|
7
|
+
* added to the VAST ad tag as `url`/`description_url` for contextual
|
|
8
|
+
* targeting. Omit it when the content URL is unknown.
|
|
9
|
+
*/
|
|
10
|
+
contentUrl?: string;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/** Options for {@link EzoicInstreamAd.reportImpression}. */
|
|
14
|
+
export interface EzoicInstreamImpressionOptions {
|
|
15
|
+
/**
|
|
16
|
+
* The publisher-reported revenue (USD) for this impression, if known. Folded
|
|
17
|
+
* into the Ezoic impression-event pixel. Omit it when no revenue is known.
|
|
18
|
+
*/
|
|
19
|
+
revenueUsd?: number;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* An instream video ad controller. Instream video runs inside the host app's
|
|
24
|
+
* OWN video content: **the host owns the video player and the Google IMA SDK**.
|
|
25
|
+
* Unlike the banner/native/outstream views, this controller renders nothing and
|
|
26
|
+
* holds no view — its sole deliverable is a GAM VAST ad-tag URL string the host
|
|
27
|
+
* feeds to its own IMA `AdsRequest`.
|
|
28
|
+
*
|
|
29
|
+
* Usage:
|
|
30
|
+
*
|
|
31
|
+
* ```ts
|
|
32
|
+
* const instream = new EzoicInstreamAd('12345');
|
|
33
|
+
* const tagUrl = await instream.load({ contentUrl: playingVideoUrl });
|
|
34
|
+
* // hand tagUrl to your IMA AdsLoader / AdsRequest.
|
|
35
|
+
*
|
|
36
|
+
* // On an IMA ad error, walk down the floor waterfall:
|
|
37
|
+
* const next = await instream.getNextAdTagUrl();
|
|
38
|
+
* if (next) { /* request IMA again with next *\/ }
|
|
39
|
+
*
|
|
40
|
+
* // On the IMA STARTED event, record the Ezoic impression:
|
|
41
|
+
* await instream.reportImpression({ revenueUsd: 0.42 });
|
|
42
|
+
*
|
|
43
|
+
* // When finished with the ad unit:
|
|
44
|
+
* await instream.destroy();
|
|
45
|
+
* ```
|
|
46
|
+
*
|
|
47
|
+
* Mirrors the native `EzoicInstreamAd` load pipeline on both platforms. Unlike
|
|
48
|
+
* the interstitial/rewarded ads, the controller is **multi-use** and NOT
|
|
49
|
+
* auto-destroying: the native controller is prefetchable and reused across
|
|
50
|
+
* loads for the same id, so the same instance can be loaded again after a
|
|
51
|
+
* previous load resolves. Call {@link destroy} when the unit is no longer
|
|
52
|
+
* needed. There is no event emitter — every result settles the returned
|
|
53
|
+
* promise directly from the native listener/delegate.
|
|
54
|
+
*/
|
|
55
|
+
export class EzoicInstreamAd {
|
|
56
|
+
/** The Ezoic ad unit identifier this controller was created for. */
|
|
57
|
+
readonly adUnitIdentifier: number;
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* @param adUnitIdentifier the Ezoic ad unit id (numeric). A string is coerced
|
|
61
|
+
* to a number so callers can pass either; a non-numeric string yields `NaN`,
|
|
62
|
+
* which the native side rejects.
|
|
63
|
+
*/
|
|
64
|
+
constructor(adUnitIdentifier: string | number) {
|
|
65
|
+
this.adUnitIdentifier = Number(adUnitIdentifier);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Loads the instream config, runs optional Prebid demand, and resolves with
|
|
70
|
+
* the GAM VAST ad-tag URL for the host's IMA player. Rejects on no fill, an
|
|
71
|
+
* uninitialized SDK, or an overlapping load already in flight for this id.
|
|
72
|
+
* Safe to call again after a previous load resolves (multi-use).
|
|
73
|
+
*/
|
|
74
|
+
load(options?: EzoicInstreamLoadOptions): Promise<string> {
|
|
75
|
+
return NativeEzoicAds.loadInstreamAd(
|
|
76
|
+
this.adUnitIdentifier,
|
|
77
|
+
options?.contentUrl ?? null
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Pops the current head off the floor waterfall and resolves with the ad tag
|
|
83
|
+
* rebuilt against the next `eb_br` hash, or `null` once the waterfall is
|
|
84
|
+
* exhausted (or before a successful {@link load} / after {@link destroy}).
|
|
85
|
+
* Call this on an IMA ad error to try the next floor.
|
|
86
|
+
*/
|
|
87
|
+
getNextAdTagUrl(): Promise<string | null> {
|
|
88
|
+
return NativeEzoicAds.getInstreamNextAdTagUrl(this.adUnitIdentifier);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Fires the Ezoic impression-event pixel for the most recently delivered tag.
|
|
93
|
+
* Call this on the IMA `STARTED` event. No-op natively when no tag has been
|
|
94
|
+
* delivered or after {@link destroy}.
|
|
95
|
+
*/
|
|
96
|
+
reportImpression(options?: EzoicInstreamImpressionOptions): Promise<void> {
|
|
97
|
+
return NativeEzoicAds.reportInstreamImpression(
|
|
98
|
+
this.adUnitIdentifier,
|
|
99
|
+
options?.revenueUsd ?? null
|
|
100
|
+
);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Cancels any in-flight load and releases the native controller for this id.
|
|
105
|
+
* A load in flight rejects. Safe to call multiple times.
|
|
106
|
+
*/
|
|
107
|
+
destroy(): Promise<void> {
|
|
108
|
+
return NativeEzoicAds.destroyInstreamAd(this.adUnitIdentifier);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { codegenNativeComponent } from 'react-native';
|
|
2
|
+
import type { CodegenTypes, HostComponent, ViewProps } from 'react-native';
|
|
3
|
+
|
|
4
|
+
type LoadEvent = Readonly<{}>;
|
|
5
|
+
type ErrorEvent = Readonly<{ message: string; code: CodegenTypes.Int32 }>;
|
|
6
|
+
|
|
7
|
+
export interface NativeProps extends ViewProps {
|
|
8
|
+
adUnitIdentifier: string;
|
|
9
|
+
onLoad?: CodegenTypes.BubblingEventHandler<LoadEvent> | null;
|
|
10
|
+
onError?: CodegenTypes.BubblingEventHandler<ErrorEvent> | null;
|
|
11
|
+
onImpression?: CodegenTypes.BubblingEventHandler<LoadEvent> | null;
|
|
12
|
+
// `onClick` is reserved by core ViewProps (a gesture handler), so the native
|
|
13
|
+
// outstream-click event is exposed as `onAdClick`. The public
|
|
14
|
+
// `EzoicOutstreamAdView` component maps the user-facing `onClick` prop onto
|
|
15
|
+
// this.
|
|
16
|
+
onAdClick?: CodegenTypes.BubblingEventHandler<LoadEvent> | null;
|
|
17
|
+
onOpen?: CodegenTypes.BubblingEventHandler<LoadEvent> | null;
|
|
18
|
+
onClose?: CodegenTypes.BubblingEventHandler<LoadEvent> | null;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export default codegenNativeComponent<NativeProps>(
|
|
22
|
+
'EzoicOutstreamAdView'
|
|
23
|
+
) as HostComponent<NativeProps>;
|
package/src/NativeEzoicAds.ts
CHANGED
|
@@ -32,6 +32,24 @@ export interface Spec extends TurboModule {
|
|
|
32
32
|
showRewardedAd(adUnitIdentifier: string): Promise<EzoicRewardResult>;
|
|
33
33
|
loadInterstitialAd(adUnitIdentifier: string): Promise<void>;
|
|
34
34
|
showInterstitialAd(adUnitIdentifier: string): Promise<void>;
|
|
35
|
+
// Instream video: the native `EzoicInstreamAd` renders nothing — its sole
|
|
36
|
+
// deliverable is a GAM VAST ad-tag URL the host feeds to its own IMA player.
|
|
37
|
+
// The id is numeric here (matches the native controller's `Int`/`Int`
|
|
38
|
+
// adUnitId) and multi-use: a controller is created-or-reused per id and is
|
|
39
|
+
// NOT auto-destroyed. `contentUrl`/`revenueUsd` are nullable unions —
|
|
40
|
+
// codegen maps them to nullable native args (String?/NSString*, Double?/
|
|
41
|
+
// NSNumber*) — because there is no optional-arg precedent for instream on
|
|
42
|
+
// this spec and the native `load`/`reportImpression` accept optionals.
|
|
43
|
+
loadInstreamAd(
|
|
44
|
+
adUnitIdentifier: number,
|
|
45
|
+
contentUrl: string | null
|
|
46
|
+
): Promise<string>;
|
|
47
|
+
getInstreamNextAdTagUrl(adUnitIdentifier: number): Promise<string | null>;
|
|
48
|
+
reportInstreamImpression(
|
|
49
|
+
adUnitIdentifier: number,
|
|
50
|
+
revenueUsd: number | null
|
|
51
|
+
): Promise<void>;
|
|
52
|
+
destroyInstreamAd(adUnitIdentifier: number): Promise<void>;
|
|
35
53
|
// Required by NativeEventEmitter for the ad lifecycle events.
|
|
36
54
|
addListener(eventName: string): void;
|
|
37
55
|
removeListeners(count: number): void;
|
package/src/index.tsx
CHANGED
|
@@ -2,6 +2,7 @@ import type { StyleProp, ViewStyle } from 'react-native';
|
|
|
2
2
|
import NativeEzoicAds, { type EzoicConfig } from './NativeEzoicAds';
|
|
3
3
|
import EzoicBannerNative from './EzoicBannerViewNativeComponent';
|
|
4
4
|
import EzoicNativeAdNative from './EzoicNativeAdViewNativeComponent';
|
|
5
|
+
import EzoicOutstreamNative from './EzoicOutstreamAdViewNativeComponent';
|
|
5
6
|
import { coerceAdUnitId, normalizeConfig, normalizeSize } from './helpers';
|
|
6
7
|
|
|
7
8
|
export type { EzoicConfig };
|
|
@@ -14,6 +15,11 @@ export {
|
|
|
14
15
|
EzoicInterstitialAd,
|
|
15
16
|
type EzoicInterstitialAdListeners,
|
|
16
17
|
} from './EzoicInterstitialAd';
|
|
18
|
+
export {
|
|
19
|
+
EzoicInstreamAd,
|
|
20
|
+
type EzoicInstreamLoadOptions,
|
|
21
|
+
type EzoicInstreamImpressionOptions,
|
|
22
|
+
} from './EzoicInstreamAd';
|
|
17
23
|
|
|
18
24
|
export const EzoicAds = {
|
|
19
25
|
initialize(config: EzoicConfig): Promise<void> {
|
|
@@ -122,3 +128,50 @@ export function EzoicNativeAdView(props: EzoicNativeAdViewProps) {
|
|
|
122
128
|
/>
|
|
123
129
|
);
|
|
124
130
|
}
|
|
131
|
+
|
|
132
|
+
export interface EzoicOutstreamAdError {
|
|
133
|
+
message: string;
|
|
134
|
+
code: number;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
export interface EzoicOutstreamAdViewProps {
|
|
138
|
+
adUnitIdentifier: string | number;
|
|
139
|
+
style?: StyleProp<ViewStyle>;
|
|
140
|
+
onLoad?: () => void;
|
|
141
|
+
onError?: (error: EzoicOutstreamAdError) => void;
|
|
142
|
+
onImpression?: () => void;
|
|
143
|
+
onClick?: () => void;
|
|
144
|
+
onOpen?: () => void;
|
|
145
|
+
onClose?: () => void;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Renders an outstream video ad in an SDK-built player. Outstream video runs on
|
|
150
|
+
* its own (not inside host video content), so the SDK owns the player and this
|
|
151
|
+
* component only needs a size. Fills the bounds it is given by its RN style, so
|
|
152
|
+
* size it with `style` (e.g. `{ width: '100%', height: 200 }`).
|
|
153
|
+
*/
|
|
154
|
+
export function EzoicOutstreamAdView(props: EzoicOutstreamAdViewProps) {
|
|
155
|
+
const {
|
|
156
|
+
adUnitIdentifier,
|
|
157
|
+
onLoad,
|
|
158
|
+
onError,
|
|
159
|
+
onImpression,
|
|
160
|
+
onClick,
|
|
161
|
+
onOpen,
|
|
162
|
+
onClose,
|
|
163
|
+
...rest
|
|
164
|
+
} = props;
|
|
165
|
+
return (
|
|
166
|
+
<EzoicOutstreamNative
|
|
167
|
+
{...rest}
|
|
168
|
+
adUnitIdentifier={coerceAdUnitId(adUnitIdentifier)}
|
|
169
|
+
onLoad={onLoad ? () => onLoad() : undefined}
|
|
170
|
+
onError={onError ? (e) => onError(e.nativeEvent) : undefined}
|
|
171
|
+
onImpression={onImpression ? () => onImpression() : undefined}
|
|
172
|
+
onAdClick={onClick ? () => onClick() : undefined}
|
|
173
|
+
onOpen={onOpen ? () => onOpen() : undefined}
|
|
174
|
+
onClose={onClose ? () => onClose() : undefined}
|
|
175
|
+
/>
|
|
176
|
+
);
|
|
177
|
+
}
|