@ezoic/react-native-sdk 1.0.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.
Files changed (35) hide show
  1. package/EzoicReactNativeSdk.podspec +25 -0
  2. package/LICENSE +18 -0
  3. package/README.md +82 -0
  4. package/android/build.gradle +72 -0
  5. package/android/src/main/AndroidManifest.xml +2 -0
  6. package/android/src/main/java/com/ezoic/reactnative/EzoicAdsModule.kt +62 -0
  7. package/android/src/main/java/com/ezoic/reactnative/EzoicBannerViewManager.kt +93 -0
  8. package/android/src/main/java/com/ezoic/reactnative/EzoicReactNativeSdkPackage.kt +37 -0
  9. package/ios/EzoicAdsImpl.swift +48 -0
  10. package/ios/EzoicBannerHostView.swift +49 -0
  11. package/ios/EzoicBannerViewComponentView.mm +67 -0
  12. package/ios/EzoicReactNativeSdk.h +5 -0
  13. package/ios/EzoicReactNativeSdk.mm +55 -0
  14. package/lib/module/EzoicBannerViewNativeComponent.ts +23 -0
  15. package/lib/module/NativeEzoicAds.js +5 -0
  16. package/lib/module/NativeEzoicAds.js.map +1 -0
  17. package/lib/module/helpers.js +24 -0
  18. package/lib/module/helpers.js.map +1 -0
  19. package/lib/module/index.js +48 -0
  20. package/lib/module/index.js.map +1 -0
  21. package/lib/module/package.json +1 -0
  22. package/lib/typescript/package.json +1 -0
  23. package/lib/typescript/src/EzoicBannerViewNativeComponent.d.ts +19 -0
  24. package/lib/typescript/src/EzoicBannerViewNativeComponent.d.ts.map +1 -0
  25. package/lib/typescript/src/NativeEzoicAds.d.ts +19 -0
  26. package/lib/typescript/src/NativeEzoicAds.d.ts.map +1 -0
  27. package/lib/typescript/src/helpers.d.ts +5 -0
  28. package/lib/typescript/src/helpers.d.ts.map +1 -0
  29. package/lib/typescript/src/index.d.ts +27 -0
  30. package/lib/typescript/src/index.d.ts.map +1 -0
  31. package/package.json +141 -0
  32. package/src/EzoicBannerViewNativeComponent.ts +23 -0
  33. package/src/NativeEzoicAds.ts +21 -0
  34. package/src/helpers.ts +30 -0
  35. package/src/index.tsx +68 -0
@@ -0,0 +1,25 @@
1
+ require "json"
2
+
3
+ package = JSON.parse(File.read(File.join(__dir__, "package.json")))
4
+
5
+ Pod::Spec.new do |s|
6
+ s.name = "EzoicReactNativeSdk"
7
+ s.version = package["version"]
8
+ s.summary = package["description"]
9
+ s.homepage = package["homepage"]
10
+ s.license = package["license"]
11
+ s.authors = package["author"]
12
+
13
+ s.platforms = { :ios => min_ios_version_supported }
14
+ s.source = { :git => "https://github.com/ezoic/react-native-sdk.git", :tag => "#{s.version}" }
15
+
16
+ s.source_files = "ios/**/*.{h,m,mm,swift,cpp}"
17
+ s.private_header_files = "ios/**/*.h"
18
+
19
+ install_modules_dependencies(s)
20
+
21
+ # Native Ezoic Ads SDK (vends the `EzoicAdsSDKBinary` module). Brings in
22
+ # PrebidMobile + Google-Mobile-Ads-SDK transitively.
23
+ s.dependency "EzoicAdsSDK", "~> 1.0"
24
+ s.swift_version = "5.9"
25
+ end
package/LICENSE ADDED
@@ -0,0 +1,18 @@
1
+ Copyright (c) 2026 Ezoic Inc. All rights reserved.
2
+
3
+ This software is licensed under proprietary terms. Use of this software
4
+ is governed by the Ezoic Terms of Service available at:
5
+
6
+ https://www.ezoic.com/terms
7
+
8
+ Redistribution, modification, or use of this software in any form
9
+ outside the scope of the Terms of Service requires the express written
10
+ permission of Ezoic Inc.
11
+
12
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
13
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
14
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
15
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
16
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
17
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
18
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,82 @@
1
+ # @ezoic/react-native-sdk
2
+
3
+ Ezoic Ads SDK for React Native (Prebid + Google Ad Manager banner ads).
4
+
5
+ A thin React Native (New Architecture) wrapper over the native Ezoic Ads SDKs
6
+ for iOS (`EzoicAdsSDK`, via CocoaPods) and Android
7
+ (`com.ezoic.sdk:ezoic-ads-sdk`, via Maven Central). It exposes an imperative
8
+ `EzoicAds` TurboModule and an `EzoicBannerView` Fabric component.
9
+
10
+ ## Requirements
11
+
12
+ - React Native 0.76+ with the New Architecture enabled.
13
+ - iOS 14.0+, Android `minSdk` 24+.
14
+
15
+ ## Installation
16
+
17
+ ```sh
18
+ npm install @ezoic/react-native-sdk
19
+ ```
20
+
21
+ ### iOS
22
+
23
+ The native `EzoicAdsSDK` ships as a binary Swift framework that depends on
24
+ `PrebidMobile` (a Swift source pod). Consuming a binary Swift framework with
25
+ Swift dependencies requires framework-based linkage, so your app's `Podfile`
26
+ must enable static frameworks:
27
+
28
+ ```ruby
29
+ use_frameworks! :linkage => :static
30
+ ```
31
+
32
+ Then install pods:
33
+
34
+ ```sh
35
+ cd ios && RCT_NEW_ARCH_ENABLED=1 pod install
36
+ ```
37
+
38
+ ## Usage
39
+
40
+ ```tsx
41
+ import { EzoicAds, EzoicBannerView } from '@ezoic/react-native-sdk';
42
+
43
+ // Initialize once, early in app startup.
44
+ await EzoicAds.initialize({ domain: 'example.com' });
45
+
46
+ // Optional consent / privacy signals.
47
+ EzoicAds.setGDPRConsent(true, '<IAB TCF consent string>');
48
+ EzoicAds.setGPPConsent('<GPP string>', '7');
49
+ EzoicAds.setSubjectToCOPPA(false);
50
+
51
+ // Track a pageview.
52
+ const tracked = await EzoicAds.trackPageview();
53
+
54
+ // Render a banner.
55
+ <EzoicBannerView
56
+ adUnitIdentifier="123456"
57
+ size="300x250"
58
+ style={{ width: 300, height: 250 }}
59
+ onLoad={() => console.log('loaded')}
60
+ onError={(e) => console.log('error', e.message, e.code)}
61
+ onImpression={() => console.log('impression')}
62
+ onClick={() => console.log('click')}
63
+ onOpen={() => console.log('open')}
64
+ onClose={() => console.log('close')}
65
+ />;
66
+ ```
67
+
68
+ `adUnitIdentifier` is a string coerced to a native integer. `size` is a `"WxH"`
69
+ string or comma-separated list (e.g. `"300x250"`, `"300x250,320x50"`).
70
+
71
+ ## API
72
+
73
+ - `EzoicAds.initialize(config)` → `Promise<void>`
74
+ - `EzoicAds.setGDPRConsent(applies, consentString?)` → `void`
75
+ - `EzoicAds.setGPPConsent(gppString?, sectionIds?)` → `void`
76
+ - `EzoicAds.setSubjectToCOPPA(value)` → `void`
77
+ - `EzoicAds.trackPageview()` → `Promise<boolean>`
78
+ - `<EzoicBannerView adUnitIdentifier size onLoad onError onImpression onClick onOpen onClose />`
79
+
80
+ ## License
81
+
82
+ SEE LICENSE IN LICENSE — Copyright (c) 2026 Ezoic Inc. All rights reserved.
@@ -0,0 +1,72 @@
1
+ buildscript {
2
+ ext.EzoicReactNativeSdk = [
3
+ kotlinVersion: "2.0.21",
4
+ minSdkVersion: 24,
5
+ compileSdkVersion: 36,
6
+ targetSdkVersion: 36
7
+ ]
8
+
9
+ ext.getExtOrDefault = { prop ->
10
+ if (rootProject.ext.has(prop)) {
11
+ return rootProject.ext.get(prop)
12
+ }
13
+
14
+ return EzoicReactNativeSdk[prop]
15
+ }
16
+
17
+ repositories {
18
+ google()
19
+ mavenCentral()
20
+ }
21
+
22
+ dependencies {
23
+ classpath "com.android.tools.build:gradle:8.7.2"
24
+ // noinspection DifferentKotlinGradleVersion
25
+ classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${getExtOrDefault('kotlinVersion')}"
26
+ }
27
+ }
28
+
29
+
30
+ apply plugin: "com.android.library"
31
+ apply plugin: "kotlin-android"
32
+
33
+ apply plugin: "com.facebook.react"
34
+
35
+ android {
36
+ namespace "com.ezoic.reactnative"
37
+
38
+ compileSdkVersion getExtOrDefault("compileSdkVersion")
39
+
40
+ defaultConfig {
41
+ minSdkVersion getExtOrDefault("minSdkVersion")
42
+ targetSdkVersion getExtOrDefault("targetSdkVersion")
43
+ }
44
+
45
+ buildFeatures {
46
+ buildConfig true
47
+ }
48
+
49
+ buildTypes {
50
+ release {
51
+ minifyEnabled false
52
+ }
53
+ }
54
+
55
+ lint {
56
+ disable "GradleCompatible"
57
+ }
58
+
59
+ compileOptions {
60
+ sourceCompatibility JavaVersion.VERSION_1_8
61
+ targetCompatibility JavaVersion.VERSION_1_8
62
+ }
63
+ }
64
+
65
+ dependencies {
66
+ implementation "com.facebook.react:react-android"
67
+
68
+ // Native Ezoic Ads SDK (resolved from Maven Central). Brings in Google Mobile
69
+ // Ads + Prebid transitively. Requires mavenCentral() + google() in the
70
+ // consuming app's repositories (the RN template provides both).
71
+ implementation "com.ezoic.sdk:ezoic-ads-sdk:1.0.0"
72
+ }
@@ -0,0 +1,2 @@
1
+ <manifest xmlns:android="http://schemas.android.com/apk/res/android">
2
+ </manifest>
@@ -0,0 +1,62 @@
1
+ package com.ezoic.reactnative
2
+
3
+ import android.app.Application
4
+ import com.facebook.react.bridge.Promise
5
+ import com.facebook.react.bridge.ReactApplicationContext
6
+ import com.facebook.react.bridge.ReadableMap
7
+ import com.ezoic.ads.sdk.core.EzoicAds
8
+ import com.ezoic.ads.sdk.core.EzoicConfiguration
9
+
10
+ class EzoicAdsModule(reactContext: ReactApplicationContext) :
11
+ NativeEzoicAdsSpec(reactContext) {
12
+
13
+ override fun getName() = NAME
14
+
15
+ override fun initialize(config: ReadableMap, promise: Promise) {
16
+ val domain = if (config.hasKey("domain")) config.getString("domain") else null
17
+ if (domain.isNullOrEmpty()) {
18
+ promise.reject("EzoicAds", "initialize requires a non-empty `domain`.")
19
+ return
20
+ }
21
+ val app = reactApplicationContext.applicationContext as? Application
22
+ if (app == null) {
23
+ promise.reject("EzoicAds", "No Application context available.")
24
+ return
25
+ }
26
+ val configuration = EzoicConfiguration(
27
+ domain = domain,
28
+ autoReadConsent = config.optBool("autoReadConsent", true),
29
+ subjectToCOPPA = config.optBool("subjectToCOPPA", false),
30
+ requestATTBeforeAds = config.optBool("requestATTBeforeAds", true),
31
+ debugEnabled = config.optBool("debugEnabled", false),
32
+ testMode = config.optBool("testMode", false)
33
+ )
34
+ EzoicAds.instance.initialize(app, configuration) { result ->
35
+ result.onSuccess { promise.resolve(null) }
36
+ .onFailure { e -> promise.reject("EzoicAds", e.message, e) }
37
+ }
38
+ }
39
+
40
+ override fun setGDPRConsent(applies: Boolean, consentString: String?) {
41
+ EzoicAds.instance.setGDPRConsent(applies, consentString)
42
+ }
43
+
44
+ override fun setGPPConsent(gppString: String?, sectionIds: String?) {
45
+ EzoicAds.instance.setGPPConsent(gppString, sectionIds)
46
+ }
47
+
48
+ override fun setSubjectToCOPPA(value: Boolean) {
49
+ EzoicAds.instance.setSubjectToCOPPA(value)
50
+ }
51
+
52
+ override fun trackPageview(promise: Promise) {
53
+ EzoicAds.instance.trackPageview { success -> promise.resolve(success) }
54
+ }
55
+
56
+ private fun ReadableMap.optBool(key: String, default: Boolean): Boolean =
57
+ if (hasKey(key) && !isNull(key)) getBoolean(key) else default
58
+
59
+ companion object {
60
+ const val NAME = NativeEzoicAdsSpec.NAME
61
+ }
62
+ }
@@ -0,0 +1,93 @@
1
+ package com.ezoic.reactnative
2
+
3
+ import android.view.ViewGroup
4
+ import android.widget.FrameLayout
5
+ import com.facebook.react.bridge.Arguments
6
+ import com.facebook.react.bridge.ReactApplicationContext
7
+ import com.facebook.react.bridge.WritableMap
8
+ import com.facebook.react.module.annotations.ReactModule
9
+ import com.facebook.react.uimanager.SimpleViewManager
10
+ import com.facebook.react.uimanager.ThemedReactContext
11
+ import com.facebook.react.uimanager.annotations.ReactProp
12
+ import com.facebook.react.uimanager.events.RCTEventEmitter
13
+ import com.ezoic.ads.sdk.adunits.EzoicBannerView
14
+ import com.ezoic.ads.sdk.adunits.EzoicBannerViewListener
15
+ import com.ezoic.ads.sdk.core.EzoicError
16
+
17
+ @ReactModule(name = EzoicBannerViewManager.NAME)
18
+ class EzoicBannerViewManager(private val ctx: ReactApplicationContext) :
19
+ SimpleViewManager<FrameLayout>() {
20
+
21
+ override fun getName() = NAME
22
+
23
+ override fun createViewInstance(reactContext: ThemedReactContext): FrameLayout {
24
+ val container = FrameLayout(reactContext)
25
+ container.layoutParams = ViewGroup.LayoutParams(
26
+ ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT
27
+ )
28
+ container.tag = BannerState()
29
+ return container
30
+ }
31
+
32
+ @ReactProp(name = "adUnitIdentifier")
33
+ fun setAdUnitIdentifier(view: FrameLayout, value: String?) {
34
+ (view.tag as BannerState).adUnitId = value?.toIntOrNull() ?: 0
35
+ maybeLoad(view)
36
+ }
37
+
38
+ @ReactProp(name = "size")
39
+ fun setSize(view: FrameLayout, value: String?) {
40
+ (view.tag as BannerState).size = value ?: ""
41
+ maybeLoad(view)
42
+ }
43
+
44
+ private fun maybeLoad(view: FrameLayout) {
45
+ val state = view.tag as BannerState
46
+ if (state.loaded || state.adUnitId <= 0) return
47
+ state.loaded = true
48
+ val banner = EzoicBannerView(view.context, state.adUnitId)
49
+ banner.listener = object : EzoicBannerViewListener {
50
+ override fun onBannerLoaded(b: EzoicBannerView) = emit(view, "topLoad", Arguments.createMap())
51
+ override fun onBannerLoadFailed(b: EzoicBannerView, error: EzoicError) {
52
+ val map = Arguments.createMap()
53
+ map.putString("message", error.message)
54
+ map.putInt("code", error.code)
55
+ emit(view, "topError", map)
56
+ }
57
+ override fun onBannerImpression(b: EzoicBannerView) = emit(view, "topImpression", Arguments.createMap())
58
+ override fun onBannerClicked(b: EzoicBannerView) = emit(view, "topAdClick", Arguments.createMap())
59
+ override fun onBannerOpened(b: EzoicBannerView) = emit(view, "topOpen", Arguments.createMap())
60
+ override fun onBannerClosed(b: EzoicBannerView) = emit(view, "topClose", Arguments.createMap())
61
+ }
62
+ view.removeAllViews()
63
+ view.addView(banner)
64
+ val sizes = state.size.split(",").map { it.trim() }.filter { it.isNotEmpty() }
65
+ if (sizes.isEmpty()) banner.loadAd() else banner.loadAd(sizes)
66
+ }
67
+
68
+ private fun emit(view: FrameLayout, event: String, payload: WritableMap) {
69
+ ctx.getJSModule(RCTEventEmitter::class.java).receiveEvent(view.id, event, payload)
70
+ }
71
+
72
+ override fun getExportedCustomBubblingEventTypeConstants(): Map<String, Any> {
73
+ fun reg(on: String) = mapOf("phasedRegistrationNames" to mapOf("bubbled" to on))
74
+ return mapOf(
75
+ "topLoad" to reg("onLoad"),
76
+ "topError" to reg("onError"),
77
+ "topImpression" to reg("onImpression"),
78
+ "topAdClick" to reg("onAdClick"),
79
+ "topOpen" to reg("onOpen"),
80
+ "topClose" to reg("onClose")
81
+ )
82
+ }
83
+
84
+ private class BannerState {
85
+ var adUnitId: Int = 0
86
+ var size: String = ""
87
+ var loaded: Boolean = false
88
+ }
89
+
90
+ companion object {
91
+ const val NAME = "EzoicBannerView"
92
+ }
93
+ }
@@ -0,0 +1,37 @@
1
+ package com.ezoic.reactnative
2
+
3
+ import com.facebook.react.BaseReactPackage
4
+ import com.facebook.react.bridge.NativeModule
5
+ import com.facebook.react.bridge.ReactApplicationContext
6
+ import com.facebook.react.module.model.ReactModuleInfo
7
+ import com.facebook.react.module.model.ReactModuleInfoProvider
8
+ import com.facebook.react.uimanager.ViewManager
9
+
10
+ class EzoicReactNativeSdkPackage : BaseReactPackage() {
11
+ override fun getModule(name: String, reactContext: ReactApplicationContext): NativeModule? {
12
+ return if (name == EzoicAdsModule.NAME) {
13
+ EzoicAdsModule(reactContext)
14
+ } else {
15
+ null
16
+ }
17
+ }
18
+
19
+ override fun createViewManagers(
20
+ reactContext: ReactApplicationContext
21
+ ): List<ViewManager<*, *>> {
22
+ return listOf(EzoicBannerViewManager(reactContext))
23
+ }
24
+
25
+ override fun getReactModuleInfoProvider() = ReactModuleInfoProvider {
26
+ mapOf(
27
+ EzoicAdsModule.NAME to ReactModuleInfo(
28
+ name = EzoicAdsModule.NAME,
29
+ className = EzoicAdsModule.NAME,
30
+ canOverrideExistingModule = false,
31
+ needsEagerInit = false,
32
+ isCxxModule = false,
33
+ isTurboModule = true
34
+ )
35
+ )
36
+ }
37
+ }
@@ -0,0 +1,48 @@
1
+ import Foundation
2
+ import EzoicAdsSDKBinary
3
+
4
+ @objc public class EzoicAdsImpl: NSObject {
5
+
6
+ @objc public func initialize(_ config: NSDictionary,
7
+ resolve: @escaping (Any?) -> Void,
8
+ reject: @escaping (String, String, NSError?) -> Void) {
9
+ guard let domain = config["domain"] as? String, !domain.isEmpty else {
10
+ reject("EzoicAds", "initialize requires a non-empty `domain`.", nil)
11
+ return
12
+ }
13
+ let configuration = EzoicConfiguration(
14
+ domain: domain,
15
+ autoReadConsent: (config["autoReadConsent"] as? Bool) ?? true,
16
+ subjectToCOPPA: (config["subjectToCOPPA"] as? Bool) ?? false,
17
+ requestATTBeforeAds: (config["requestATTBeforeAds"] as? Bool) ?? true,
18
+ debugEnabled: (config["debugEnabled"] as? Bool) ?? false,
19
+ testMode: (config["testMode"] as? Bool) ?? false
20
+ )
21
+ EzoicAds.shared.initialize(with: configuration) { result in
22
+ switch result {
23
+ case .success:
24
+ resolve(nil)
25
+ case .failure(let error):
26
+ reject("EzoicAds", error.localizedDescription, error as NSError)
27
+ }
28
+ }
29
+ }
30
+
31
+ @objc public func setGDPRConsent(_ applies: Bool, consentString: String?) {
32
+ EzoicAds.shared.setGDPRConsent(applies: applies, consentString: consentString)
33
+ }
34
+
35
+ @objc public func setGPPConsent(_ gppString: String?, sectionIds: String?) {
36
+ EzoicAds.shared.setGPPConsent(gppString: gppString, sectionIds: sectionIds)
37
+ }
38
+
39
+ @objc public func setSubjectToCOPPA(_ value: Bool) {
40
+ EzoicAds.shared.setSubjectToCOPPA(value)
41
+ }
42
+
43
+ @objc public func trackPageview(_ resolve: @escaping (Any?) -> Void) {
44
+ EzoicAds.shared.trackPageview { success in
45
+ resolve(NSNumber(value: success))
46
+ }
47
+ }
48
+ }
@@ -0,0 +1,49 @@
1
+ import UIKit
2
+ import EzoicAdsSDKBinary
3
+
4
+ @objc public protocol EzoicBannerHostViewDelegate: AnyObject {
5
+ func bannerDidLoad()
6
+ func bannerDidFail(_ message: String, code: Int)
7
+ func bannerDidRecordImpression()
8
+ func bannerDidRecordClick()
9
+ func bannerWillPresentScreen()
10
+ func bannerDidDismissScreen()
11
+ }
12
+
13
+ @objc public class EzoicBannerHostView: UIView, EzoicBannerViewDelegate {
14
+
15
+ @objc public weak var hostDelegate: EzoicBannerHostViewDelegate?
16
+ private var banner: EzoicBannerView?
17
+ private var adUnitId: Int = 0
18
+ private var sizes: [String] = []
19
+
20
+ @objc public func configure(adUnitIdentifier: String, size: String) {
21
+ self.adUnitId = Int(adUnitIdentifier) ?? 0
22
+ self.sizes = size.split(separator: ",").map { String($0) }
23
+ rebuildAndLoad()
24
+ }
25
+
26
+ private func rebuildAndLoad() {
27
+ banner?.removeFromSuperview()
28
+ let view = EzoicBannerView(adUnitIdentifier: adUnitId)
29
+ view.delegate = self
30
+ view.translatesAutoresizingMaskIntoConstraints = false
31
+ addSubview(view)
32
+ NSLayoutConstraint.activate([
33
+ view.centerXAnchor.constraint(equalTo: centerXAnchor),
34
+ view.centerYAnchor.constraint(equalTo: centerYAnchor),
35
+ ])
36
+ banner = view
37
+ if sizes.isEmpty { view.loadAd() } else { view.loadAd(sizes: sizes) }
38
+ }
39
+
40
+ // MARK: - EzoicBannerViewDelegate
41
+ public func bannerViewDidLoad(_ bannerView: EzoicBannerView) { hostDelegate?.bannerDidLoad() }
42
+ public func bannerView(_ bannerView: EzoicBannerView, didFailToLoadWithError error: EzoicError) {
43
+ hostDelegate?.bannerDidFail(error.localizedDescription, code: error.code)
44
+ }
45
+ public func bannerViewDidRecordImpression(_ bannerView: EzoicBannerView) { hostDelegate?.bannerDidRecordImpression() }
46
+ public func bannerViewDidRecordClick(_ bannerView: EzoicBannerView) { hostDelegate?.bannerDidRecordClick() }
47
+ public func bannerViewWillPresentScreen(_ bannerView: EzoicBannerView) { hostDelegate?.bannerWillPresentScreen() }
48
+ public func bannerViewDidDismissScreen(_ bannerView: EzoicBannerView) { hostDelegate?.bannerDidDismissScreen() }
49
+ }
@@ -0,0 +1,67 @@
1
+ #import <React/RCTViewComponentView.h>
2
+ #import <react/renderer/components/EzoicReactNativeSdkSpec/ComponentDescriptors.h>
3
+ #import <react/renderer/components/EzoicReactNativeSdkSpec/EventEmitters.h>
4
+ #import <react/renderer/components/EzoicReactNativeSdkSpec/Props.h>
5
+ #import <react/renderer/components/EzoicReactNativeSdkSpec/RCTComponentViewHelpers.h>
6
+ #import <EzoicReactNativeSdk/EzoicReactNativeSdk-Swift.h>
7
+
8
+ using namespace facebook::react;
9
+
10
+ @interface EzoicBannerView : RCTViewComponentView <EzoicBannerHostViewDelegate>
11
+ @end
12
+
13
+ @implementation EzoicBannerView {
14
+ EzoicBannerHostView *_host;
15
+ NSString *_lastAdUnit;
16
+ NSString *_lastSize;
17
+ }
18
+
19
+ + (ComponentDescriptorProvider)componentDescriptorProvider {
20
+ return concreteComponentDescriptorProvider<EzoicBannerViewComponentDescriptor>();
21
+ }
22
+
23
+ - (instancetype)initWithFrame:(CGRect)frame {
24
+ if (self = [super initWithFrame:frame]) {
25
+ _host = [EzoicBannerHostView new];
26
+ _host.hostDelegate = self;
27
+ self.contentView = _host;
28
+ }
29
+ return self;
30
+ }
31
+
32
+ - (void)updateProps:(Props::Shared const &)props oldProps:(Props::Shared const &)oldProps {
33
+ const auto &newProps = *std::static_pointer_cast<EzoicBannerViewProps const>(props);
34
+ NSString *adUnit = [NSString stringWithUTF8String:newProps.adUnitIdentifier.c_str()];
35
+ NSString *size = [NSString stringWithUTF8String:newProps.size.c_str()];
36
+ if (![adUnit isEqualToString:_lastAdUnit] || ![size isEqualToString:_lastSize]) {
37
+ _lastAdUnit = adUnit;
38
+ _lastSize = size;
39
+ [_host configureWithAdUnitIdentifier:adUnit size:size];
40
+ }
41
+ [super updateProps:props oldProps:oldProps];
42
+ }
43
+
44
+ - (void)bannerDidLoad {
45
+ if (_eventEmitter) std::static_pointer_cast<EzoicBannerViewEventEmitter const>(_eventEmitter)->onLoad({});
46
+ }
47
+ - (void)bannerDidFail:(NSString *)message code:(NSInteger)code {
48
+ if (_eventEmitter)
49
+ std::static_pointer_cast<EzoicBannerViewEventEmitter const>(_eventEmitter)
50
+ ->onError({.message = std::string([message UTF8String]), .code = (int)code});
51
+ }
52
+ - (void)bannerDidRecordImpression {
53
+ if (_eventEmitter) std::static_pointer_cast<EzoicBannerViewEventEmitter const>(_eventEmitter)->onImpression({});
54
+ }
55
+ - (void)bannerDidRecordClick {
56
+ if (_eventEmitter) std::static_pointer_cast<EzoicBannerViewEventEmitter const>(_eventEmitter)->onAdClick({});
57
+ }
58
+ - (void)bannerWillPresentScreen {
59
+ if (_eventEmitter) std::static_pointer_cast<EzoicBannerViewEventEmitter const>(_eventEmitter)->onOpen({});
60
+ }
61
+ - (void)bannerDidDismissScreen {
62
+ if (_eventEmitter) std::static_pointer_cast<EzoicBannerViewEventEmitter const>(_eventEmitter)->onClose({});
63
+ }
64
+
65
+ Class<RCTComponentViewProtocol> EzoicBannerViewCls(void) { return EzoicBannerView.class; }
66
+
67
+ @end
@@ -0,0 +1,5 @@
1
+ #import <EzoicReactNativeSdkSpec/EzoicReactNativeSdkSpec.h>
2
+
3
+ @interface EzoicReactNativeSdk : NSObject <NativeEzoicAdsSpec>
4
+
5
+ @end
@@ -0,0 +1,55 @@
1
+ #import "EzoicReactNativeSdk.h"
2
+ #import <EzoicReactNativeSdk/EzoicReactNativeSdk-Swift.h>
3
+
4
+ @implementation EzoicReactNativeSdk {
5
+ EzoicAdsImpl *_impl;
6
+ }
7
+
8
+ - (instancetype)init {
9
+ if (self = [super init]) {
10
+ _impl = [EzoicAdsImpl new];
11
+ }
12
+ return self;
13
+ }
14
+
15
+ - (void)initialize:(JS::NativeEzoicAds::EzoicConfig &)config
16
+ resolve:(RCTPromiseResolveBlock)resolve
17
+ reject:(RCTPromiseRejectBlock)reject {
18
+ NSMutableDictionary *dict = [NSMutableDictionary new];
19
+ dict[@"domain"] = config.domain();
20
+ if (config.autoReadConsent().has_value()) dict[@"autoReadConsent"] = @(config.autoReadConsent().value());
21
+ if (config.subjectToCOPPA().has_value()) dict[@"subjectToCOPPA"] = @(config.subjectToCOPPA().value());
22
+ if (config.requestATTBeforeAds().has_value()) dict[@"requestATTBeforeAds"] = @(config.requestATTBeforeAds().value());
23
+ if (config.debugEnabled().has_value()) dict[@"debugEnabled"] = @(config.debugEnabled().value());
24
+ if (config.testMode().has_value()) dict[@"testMode"] = @(config.testMode().value());
25
+ [_impl initialize:dict
26
+ resolve:^(id _Nullable v) { resolve(v); }
27
+ reject:^(NSString *code, NSString *msg, NSError *_Nullable e) { reject(code, msg, e); }];
28
+ }
29
+
30
+ - (void)setGDPRConsent:(BOOL)applies consentString:(NSString *)consentString {
31
+ [_impl setGDPRConsent:applies consentString:consentString];
32
+ }
33
+
34
+ - (void)setGPPConsent:(NSString *)gppString sectionIds:(NSString *)sectionIds {
35
+ [_impl setGPPConsent:gppString sectionIds:sectionIds];
36
+ }
37
+
38
+ - (void)setSubjectToCOPPA:(BOOL)value {
39
+ [_impl setSubjectToCOPPA:value];
40
+ }
41
+
42
+ - (void)trackPageview:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject {
43
+ [_impl trackPageview:^(id _Nullable v) { resolve(v); }];
44
+ }
45
+
46
+ - (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:
47
+ (const facebook::react::ObjCTurboModule::InitParams &)params {
48
+ return std::make_shared<facebook::react::NativeEzoicAdsSpecJSI>(params);
49
+ }
50
+
51
+ + (NSString *)moduleName {
52
+ return @"EzoicReactNativeSdk";
53
+ }
54
+
55
+ @end
@@ -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
+ size?: string;
10
+ onLoad?: CodegenTypes.BubblingEventHandler<LoadEvent> | null;
11
+ onError?: CodegenTypes.BubblingEventHandler<ErrorEvent> | null;
12
+ onImpression?: CodegenTypes.BubblingEventHandler<LoadEvent> | null;
13
+ // `onClick` is reserved by core ViewProps (a gesture handler), so the native
14
+ // banner-click event is exposed as `onAdClick`. The public `EzoicBannerView`
15
+ // component maps the user-facing `onClick` prop onto 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
+ 'EzoicBannerView'
23
+ ) as HostComponent<NativeProps>;
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+
3
+ import { TurboModuleRegistry } from 'react-native';
4
+ export default TurboModuleRegistry.getEnforcing('EzoicReactNativeSdk');
5
+ //# sourceMappingURL=NativeEzoicAds.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["TurboModuleRegistry","getEnforcing"],"sourceRoot":"../../src","sources":["NativeEzoicAds.ts"],"mappings":";;AACA,SAASA,mBAAmB,QAAQ,cAAc;AAmBlD,eAAeA,mBAAmB,CAACC,YAAY,CAAO,qBAAqB,CAAC","ignoreList":[]}
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+
3
+ export function normalizeConfig(config) {
4
+ if (!config || !config.domain) {
5
+ throw new Error('EzoicAds.initialize requires a non-empty `domain`.');
6
+ }
7
+ const out = {
8
+ domain: config.domain
9
+ };
10
+ if (config.autoReadConsent !== undefined) out.autoReadConsent = config.autoReadConsent;
11
+ if (config.subjectToCOPPA !== undefined) out.subjectToCOPPA = config.subjectToCOPPA;
12
+ if (config.requestATTBeforeAds !== undefined) out.requestATTBeforeAds = config.requestATTBeforeAds;
13
+ if (config.debugEnabled !== undefined) out.debugEnabled = config.debugEnabled;
14
+ if (config.testMode !== undefined) out.testMode = config.testMode;
15
+ return out;
16
+ }
17
+ export function normalizeSize(size) {
18
+ if (!size) return '';
19
+ return size.split(',').map(s => s.trim()).filter(s => s.length > 0).join(',');
20
+ }
21
+ export function coerceAdUnitId(adUnitIdentifier) {
22
+ return String(adUnitIdentifier);
23
+ }
24
+ //# sourceMappingURL=helpers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["normalizeConfig","config","domain","Error","out","autoReadConsent","undefined","subjectToCOPPA","requestATTBeforeAds","debugEnabled","testMode","normalizeSize","size","split","map","s","trim","filter","length","join","coerceAdUnitId","adUnitIdentifier","String"],"sourceRoot":"../../src","sources":["helpers.ts"],"mappings":";;AAEA,OAAO,SAASA,eAAeA,CAACC,MAAmB,EAAe;EAChE,IAAI,CAACA,MAAM,IAAI,CAACA,MAAM,CAACC,MAAM,EAAE;IAC7B,MAAM,IAAIC,KAAK,CAAC,oDAAoD,CAAC;EACvE;EACA,MAAMC,GAAgB,GAAG;IAAEF,MAAM,EAAED,MAAM,CAACC;EAAO,CAAC;EAClD,IAAID,MAAM,CAACI,eAAe,KAAKC,SAAS,EACtCF,GAAG,CAACC,eAAe,GAAGJ,MAAM,CAACI,eAAe;EAC9C,IAAIJ,MAAM,CAACM,cAAc,KAAKD,SAAS,EACrCF,GAAG,CAACG,cAAc,GAAGN,MAAM,CAACM,cAAc;EAC5C,IAAIN,MAAM,CAACO,mBAAmB,KAAKF,SAAS,EAC1CF,GAAG,CAACI,mBAAmB,GAAGP,MAAM,CAACO,mBAAmB;EACtD,IAAIP,MAAM,CAACQ,YAAY,KAAKH,SAAS,EAAEF,GAAG,CAACK,YAAY,GAAGR,MAAM,CAACQ,YAAY;EAC7E,IAAIR,MAAM,CAACS,QAAQ,KAAKJ,SAAS,EAAEF,GAAG,CAACM,QAAQ,GAAGT,MAAM,CAACS,QAAQ;EACjE,OAAON,GAAG;AACZ;AAEA,OAAO,SAASO,aAAaA,CAACC,IAAwB,EAAU;EAC9D,IAAI,CAACA,IAAI,EAAE,OAAO,EAAE;EACpB,OAAOA,IAAI,CACRC,KAAK,CAAC,GAAG,CAAC,CACVC,GAAG,CAAEC,CAAC,IAAKA,CAAC,CAACC,IAAI,CAAC,CAAC,CAAC,CACpBC,MAAM,CAAEF,CAAC,IAAKA,CAAC,CAACG,MAAM,GAAG,CAAC,CAAC,CAC3BC,IAAI,CAAC,GAAG,CAAC;AACd;AAEA,OAAO,SAASC,cAAcA,CAACC,gBAAwB,EAAU;EAC/D,OAAOC,MAAM,CAACD,gBAAgB,CAAC;AACjC","ignoreList":[]}
@@ -0,0 +1,48 @@
1
+ "use strict";
2
+
3
+ import NativeEzoicAds from "./NativeEzoicAds.js";
4
+ import EzoicBannerNative from './EzoicBannerViewNativeComponent';
5
+ import { coerceAdUnitId, normalizeConfig, normalizeSize } from "./helpers.js";
6
+ import { jsx as _jsx } from "react/jsx-runtime";
7
+ export const EzoicAds = {
8
+ initialize(config) {
9
+ return NativeEzoicAds.initialize(normalizeConfig(config));
10
+ },
11
+ setGDPRConsent(applies, consentString) {
12
+ NativeEzoicAds.setGDPRConsent(applies, consentString);
13
+ },
14
+ setGPPConsent(gppString, sectionIds) {
15
+ NativeEzoicAds.setGPPConsent(gppString, sectionIds);
16
+ },
17
+ setSubjectToCOPPA(value) {
18
+ NativeEzoicAds.setSubjectToCOPPA(value);
19
+ },
20
+ trackPageview() {
21
+ return NativeEzoicAds.trackPageview();
22
+ }
23
+ };
24
+ export function EzoicBannerView(props) {
25
+ const {
26
+ adUnitIdentifier,
27
+ size,
28
+ onLoad,
29
+ onError,
30
+ onImpression,
31
+ onClick,
32
+ onOpen,
33
+ onClose,
34
+ ...rest
35
+ } = props;
36
+ return /*#__PURE__*/_jsx(EzoicBannerNative, {
37
+ ...rest,
38
+ adUnitIdentifier: coerceAdUnitId(adUnitIdentifier),
39
+ size: normalizeSize(size),
40
+ onLoad: onLoad ? () => onLoad() : undefined,
41
+ onError: onError ? e => onError(e.nativeEvent) : undefined,
42
+ onImpression: onImpression ? () => onImpression() : undefined,
43
+ onAdClick: onClick ? () => onClick() : undefined,
44
+ onOpen: onOpen ? () => onOpen() : undefined,
45
+ onClose: onClose ? () => onClose() : undefined
46
+ });
47
+ }
48
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["NativeEzoicAds","EzoicBannerNative","coerceAdUnitId","normalizeConfig","normalizeSize","jsx","_jsx","EzoicAds","initialize","config","setGDPRConsent","applies","consentString","setGPPConsent","gppString","sectionIds","setSubjectToCOPPA","value","trackPageview","EzoicBannerView","props","adUnitIdentifier","size","onLoad","onError","onImpression","onClick","onOpen","onClose","rest","undefined","e","nativeEvent","onAdClick"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":";;AACA,OAAOA,cAAc,MAA4B,qBAAkB;AACnE,OAAOC,iBAAiB,MAAM,kCAAkC;AAChE,SAASC,cAAc,EAAEC,eAAe,EAAEC,aAAa,QAAQ,cAAW;AAAC,SAAAC,GAAA,IAAAC,IAAA;AAI3E,OAAO,MAAMC,QAAQ,GAAG;EACtBC,UAAUA,CAACC,MAAmB,EAAiB;IAC7C,OAAOT,cAAc,CAACQ,UAAU,CAACL,eAAe,CAACM,MAAM,CAAC,CAAC;EAC3D,CAAC;EACDC,cAAcA,CAACC,OAAgB,EAAEC,aAAsB,EAAQ;IAC7DZ,cAAc,CAACU,cAAc,CAACC,OAAO,EAAEC,aAAa,CAAC;EACvD,CAAC;EACDC,aAAaA,CAACC,SAAkB,EAAEC,UAAmB,EAAQ;IAC3Df,cAAc,CAACa,aAAa,CAACC,SAAS,EAAEC,UAAU,CAAC;EACrD,CAAC;EACDC,iBAAiBA,CAACC,KAAc,EAAQ;IACtCjB,cAAc,CAACgB,iBAAiB,CAACC,KAAK,CAAC;EACzC,CAAC;EACDC,aAAaA,CAAA,EAAqB;IAChC,OAAOlB,cAAc,CAACkB,aAAa,CAAC,CAAC;EACvC;AACF,CAAC;AAmBD,OAAO,SAASC,eAAeA,CAACC,KAA2B,EAAE;EAC3D,MAAM;IACJC,gBAAgB;IAChBC,IAAI;IACJC,MAAM;IACNC,OAAO;IACPC,YAAY;IACZC,OAAO;IACPC,MAAM;IACNC,OAAO;IACP,GAAGC;EACL,CAAC,GAAGT,KAAK;EACT,oBACEd,IAAA,CAACL,iBAAiB;IAAA,GACZ4B,IAAI;IACRR,gBAAgB,EAAEnB,cAAc,CAACmB,gBAAgB,CAAE;IACnDC,IAAI,EAAElB,aAAa,CAACkB,IAAI,CAAE;IAC1BC,MAAM,EAAEA,MAAM,GAAG,MAAMA,MAAM,CAAC,CAAC,GAAGO,SAAU;IAC5CN,OAAO,EAAEA,OAAO,GAAIO,CAAC,IAAKP,OAAO,CAACO,CAAC,CAACC,WAAW,CAAC,GAAGF,SAAU;IAC7DL,YAAY,EAAEA,YAAY,GAAG,MAAMA,YAAY,CAAC,CAAC,GAAGK,SAAU;IAC9DG,SAAS,EAAEP,OAAO,GAAG,MAAMA,OAAO,CAAC,CAAC,GAAGI,SAAU;IACjDH,MAAM,EAAEA,MAAM,GAAG,MAAMA,MAAM,CAAC,CAAC,GAAGG,SAAU;IAC5CF,OAAO,EAAEA,OAAO,GAAG,MAAMA,OAAO,CAAC,CAAC,GAAGE;EAAU,CAChD,CAAC;AAEN","ignoreList":[]}
@@ -0,0 +1 @@
1
+ {"type":"module"}
@@ -0,0 +1 @@
1
+ {"type":"module"}
@@ -0,0 +1,19 @@
1
+ import type { CodegenTypes, HostComponent, ViewProps } from 'react-native';
2
+ type LoadEvent = Readonly<{}>;
3
+ type ErrorEvent = Readonly<{
4
+ message: string;
5
+ code: CodegenTypes.Int32;
6
+ }>;
7
+ export interface NativeProps extends ViewProps {
8
+ adUnitIdentifier: string;
9
+ size?: string;
10
+ onLoad?: CodegenTypes.BubblingEventHandler<LoadEvent> | null;
11
+ onError?: CodegenTypes.BubblingEventHandler<ErrorEvent> | null;
12
+ onImpression?: CodegenTypes.BubblingEventHandler<LoadEvent> | null;
13
+ onAdClick?: CodegenTypes.BubblingEventHandler<LoadEvent> | null;
14
+ onOpen?: CodegenTypes.BubblingEventHandler<LoadEvent> | null;
15
+ onClose?: CodegenTypes.BubblingEventHandler<LoadEvent> | null;
16
+ }
17
+ declare const _default: HostComponent<NativeProps>;
18
+ export default _default;
19
+ //# sourceMappingURL=EzoicBannerViewNativeComponent.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"EzoicBannerViewNativeComponent.d.ts","sourceRoot":"","sources":["../../../src/EzoicBannerViewNativeComponent.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAE3E,KAAK,SAAS,GAAG,QAAQ,CAAC,EAAE,CAAC,CAAC;AAC9B,KAAK,UAAU,GAAG,QAAQ,CAAC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,YAAY,CAAC,KAAK,CAAA;CAAE,CAAC,CAAC;AAE1E,MAAM,WAAW,WAAY,SAAQ,SAAS;IAC5C,gBAAgB,EAAE,MAAM,CAAC;IACzB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,YAAY,CAAC,oBAAoB,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC;IAC7D,OAAO,CAAC,EAAE,YAAY,CAAC,oBAAoB,CAAC,UAAU,CAAC,GAAG,IAAI,CAAC;IAC/D,YAAY,CAAC,EAAE,YAAY,CAAC,oBAAoB,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC;IAInE,SAAS,CAAC,EAAE,YAAY,CAAC,oBAAoB,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC;IAChE,MAAM,CAAC,EAAE,YAAY,CAAC,oBAAoB,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC;IAC7D,OAAO,CAAC,EAAE,YAAY,CAAC,oBAAoB,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC;CAC/D;wBAII,aAAa,CAAC,WAAW,CAAC;AAF/B,wBAEgC"}
@@ -0,0 +1,19 @@
1
+ import type { TurboModule } from 'react-native';
2
+ export interface EzoicConfig {
3
+ domain: string;
4
+ autoReadConsent?: boolean;
5
+ subjectToCOPPA?: boolean;
6
+ requestATTBeforeAds?: boolean;
7
+ debugEnabled?: boolean;
8
+ testMode?: boolean;
9
+ }
10
+ export interface Spec extends TurboModule {
11
+ initialize(config: EzoicConfig): Promise<void>;
12
+ setGDPRConsent(applies: boolean, consentString?: string): void;
13
+ setGPPConsent(gppString?: string, sectionIds?: string): void;
14
+ setSubjectToCOPPA(value: boolean): void;
15
+ trackPageview(): Promise<boolean>;
16
+ }
17
+ declare const _default: Spec;
18
+ export default _default;
19
+ //# sourceMappingURL=NativeEzoicAds.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NativeEzoicAds.d.ts","sourceRoot":"","sources":["../../../src/NativeEzoicAds.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAGhD,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,IAAK,SAAQ,WAAW;IACvC,UAAU,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/C,cAAc,CAAC,OAAO,EAAE,OAAO,EAAE,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/D,aAAa,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7D,iBAAiB,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CAAC;IACxC,aAAa,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;CACnC;;AAED,wBAA6E"}
@@ -0,0 +1,5 @@
1
+ import type { EzoicConfig } from './NativeEzoicAds.js';
2
+ export declare function normalizeConfig(config: EzoicConfig): EzoicConfig;
3
+ export declare function normalizeSize(size: string | undefined): string;
4
+ export declare function coerceAdUnitId(adUnitIdentifier: string): string;
5
+ //# sourceMappingURL=helpers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../../src/helpers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAkB,CAAC;AAEpD,wBAAgB,eAAe,CAAC,MAAM,EAAE,WAAW,GAAG,WAAW,CAchE;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAO9D;AAED,wBAAgB,cAAc,CAAC,gBAAgB,EAAE,MAAM,GAAG,MAAM,CAE/D"}
@@ -0,0 +1,27 @@
1
+ import type { StyleProp, ViewStyle } from 'react-native';
2
+ import { type EzoicConfig } from './NativeEzoicAds.js';
3
+ export type { EzoicConfig };
4
+ export declare const EzoicAds: {
5
+ initialize(config: EzoicConfig): Promise<void>;
6
+ setGDPRConsent(applies: boolean, consentString?: string): void;
7
+ setGPPConsent(gppString?: string, sectionIds?: string): void;
8
+ setSubjectToCOPPA(value: boolean): void;
9
+ trackPageview(): Promise<boolean>;
10
+ };
11
+ export interface EzoicBannerError {
12
+ message: string;
13
+ code: number;
14
+ }
15
+ export interface EzoicBannerViewProps {
16
+ adUnitIdentifier: string;
17
+ size?: string;
18
+ style?: StyleProp<ViewStyle>;
19
+ onLoad?: () => void;
20
+ onError?: (error: EzoicBannerError) => void;
21
+ onImpression?: () => void;
22
+ onClick?: () => void;
23
+ onOpen?: () => void;
24
+ onClose?: () => void;
25
+ }
26
+ export declare function EzoicBannerView(props: EzoicBannerViewProps): import("react").JSX.Element;
27
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzD,OAAuB,EAAE,KAAK,WAAW,EAAE,MAAM,qBAAkB,CAAC;AAIpE,YAAY,EAAE,WAAW,EAAE,CAAC;AAE5B,eAAO,MAAM,QAAQ;uBACA,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;4BAGtB,OAAO,kBAAkB,MAAM,GAAG,IAAI;8BAGpC,MAAM,eAAe,MAAM,GAAG,IAAI;6BAGnC,OAAO,GAAG,IAAI;qBAGtB,OAAO,CAAC,OAAO,CAAC;CAGlC,CAAC;AAEF,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,oBAAoB;IACnC,gBAAgB,EAAE,MAAM,CAAC;IACzB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC7B,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,gBAAgB,KAAK,IAAI,CAAC;IAC5C,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;IAC1B,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CACtB;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,oBAAoB,+BAyB1D"}
package/package.json ADDED
@@ -0,0 +1,141 @@
1
+ {
2
+ "name": "@ezoic/react-native-sdk",
3
+ "version": "1.0.0",
4
+ "description": "Ezoic Ads SDK for React Native (Prebid + Google Ad Manager banner ads).",
5
+ "main": "./lib/module/index.js",
6
+ "types": "./lib/typescript/src/index.d.ts",
7
+ "exports": {
8
+ ".": {
9
+ "source": "./src/index.tsx",
10
+ "types": "./lib/typescript/src/index.d.ts",
11
+ "default": "./lib/module/index.js"
12
+ },
13
+ "./package.json": "./package.json"
14
+ },
15
+ "files": [
16
+ "src",
17
+ "lib",
18
+ "android",
19
+ "ios",
20
+ "cpp",
21
+ "*.podspec",
22
+ "react-native.config.js",
23
+ "!ios/build",
24
+ "!android/build",
25
+ "!android/gradle",
26
+ "!android/gradlew",
27
+ "!android/gradlew.bat",
28
+ "!android/local.properties",
29
+ "!**/__tests__",
30
+ "!**/__fixtures__",
31
+ "!**/__mocks__",
32
+ "!**/.*"
33
+ ],
34
+ "scripts": {
35
+ "clean": "del-cli android/build lib",
36
+ "prepare": "bob build",
37
+ "typecheck": "tsc",
38
+ "test": "jest",
39
+ "lint": "eslint \"**/*.{js,ts,tsx}\""
40
+ },
41
+ "keywords": [
42
+ "react-native",
43
+ "ios",
44
+ "android",
45
+ "ezoic",
46
+ "ads",
47
+ "prebid",
48
+ "google-ad-manager"
49
+ ],
50
+ "repository": {
51
+ "type": "git",
52
+ "url": "git+https://github.com/ezoic/react-native-sdk.git"
53
+ },
54
+ "author": "Ezoic Inc <support@ezoic.com> (https://www.ezoic.com)",
55
+ "license": "SEE LICENSE IN LICENSE",
56
+ "bugs": {
57
+ "url": "https://github.com/ezoic/react-native-sdk/issues"
58
+ },
59
+ "homepage": "https://github.com/ezoic/react-native-sdk#readme",
60
+ "publishConfig": {
61
+ "access": "public",
62
+ "registry": "https://registry.npmjs.org/"
63
+ },
64
+ "devDependencies": {
65
+ "@eslint/compat": "^2.1.0",
66
+ "@eslint/eslintrc": "^3.3.5",
67
+ "@eslint/js": "^10.0.1",
68
+ "@react-native/babel-preset": "0.85.0",
69
+ "@react-native/eslint-config": "0.85.0",
70
+ "@types/jest": "^29.5.12",
71
+ "@types/react": "^19.2.0",
72
+ "babel-jest": "^29.7.0",
73
+ "del-cli": "^7.0.0",
74
+ "eslint": "^9.39.4",
75
+ "eslint-config-prettier": "^10.1.8",
76
+ "eslint-plugin-ft-flow": "^3.0.11",
77
+ "eslint-plugin-prettier": "^5.5.6",
78
+ "jest": "^29.7.0",
79
+ "prettier": "^3.8.3",
80
+ "react": "19.2.3",
81
+ "react-native": "0.85.0",
82
+ "react-native-builder-bob": "^0.42.1",
83
+ "typescript": "^6.0.3"
84
+ },
85
+ "peerDependencies": {
86
+ "react": "*",
87
+ "react-native": "*"
88
+ },
89
+ "react-native-builder-bob": {
90
+ "source": "src",
91
+ "output": "lib",
92
+ "targets": [
93
+ [
94
+ "module",
95
+ {
96
+ "esm": true
97
+ }
98
+ ],
99
+ [
100
+ "typescript",
101
+ {
102
+ "project": "tsconfig.build.json"
103
+ }
104
+ ]
105
+ ]
106
+ },
107
+ "codegenConfig": {
108
+ "name": "EzoicReactNativeSdkSpec",
109
+ "type": "all",
110
+ "jsSrcsDir": "src",
111
+ "android": {
112
+ "javaPackageName": "com.ezoic.reactnative"
113
+ }
114
+ },
115
+ "jest": {
116
+ "transform": {
117
+ "^.+\\.[jt]sx?$": "babel-jest"
118
+ },
119
+ "testEnvironment": "node",
120
+ "testPathIgnorePatterns": [
121
+ "/node_modules/",
122
+ "/lib/"
123
+ ]
124
+ },
125
+ "prettier": {
126
+ "quoteProps": "consistent",
127
+ "singleQuote": true,
128
+ "tabWidth": 2,
129
+ "trailingComma": "es5",
130
+ "useTabs": false
131
+ },
132
+ "create-react-native-library": {
133
+ "type": "turbo-module",
134
+ "languages": "kotlin-objc",
135
+ "tools": [
136
+ "eslint",
137
+ "jest"
138
+ ],
139
+ "version": "0.62.1"
140
+ }
141
+ }
@@ -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
+ size?: string;
10
+ onLoad?: CodegenTypes.BubblingEventHandler<LoadEvent> | null;
11
+ onError?: CodegenTypes.BubblingEventHandler<ErrorEvent> | null;
12
+ onImpression?: CodegenTypes.BubblingEventHandler<LoadEvent> | null;
13
+ // `onClick` is reserved by core ViewProps (a gesture handler), so the native
14
+ // banner-click event is exposed as `onAdClick`. The public `EzoicBannerView`
15
+ // component maps the user-facing `onClick` prop onto 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
+ 'EzoicBannerView'
23
+ ) as HostComponent<NativeProps>;
@@ -0,0 +1,21 @@
1
+ import type { TurboModule } from 'react-native';
2
+ import { TurboModuleRegistry } from 'react-native';
3
+
4
+ export interface EzoicConfig {
5
+ domain: string;
6
+ autoReadConsent?: boolean;
7
+ subjectToCOPPA?: boolean;
8
+ requestATTBeforeAds?: boolean;
9
+ debugEnabled?: boolean;
10
+ testMode?: boolean;
11
+ }
12
+
13
+ export interface Spec extends TurboModule {
14
+ initialize(config: EzoicConfig): Promise<void>;
15
+ setGDPRConsent(applies: boolean, consentString?: string): void;
16
+ setGPPConsent(gppString?: string, sectionIds?: string): void;
17
+ setSubjectToCOPPA(value: boolean): void;
18
+ trackPageview(): Promise<boolean>;
19
+ }
20
+
21
+ export default TurboModuleRegistry.getEnforcing<Spec>('EzoicReactNativeSdk');
package/src/helpers.ts ADDED
@@ -0,0 +1,30 @@
1
+ import type { EzoicConfig } from './NativeEzoicAds';
2
+
3
+ export function normalizeConfig(config: EzoicConfig): EzoicConfig {
4
+ if (!config || !config.domain) {
5
+ throw new Error('EzoicAds.initialize requires a non-empty `domain`.');
6
+ }
7
+ const out: EzoicConfig = { domain: config.domain };
8
+ if (config.autoReadConsent !== undefined)
9
+ out.autoReadConsent = config.autoReadConsent;
10
+ if (config.subjectToCOPPA !== undefined)
11
+ out.subjectToCOPPA = config.subjectToCOPPA;
12
+ if (config.requestATTBeforeAds !== undefined)
13
+ out.requestATTBeforeAds = config.requestATTBeforeAds;
14
+ if (config.debugEnabled !== undefined) out.debugEnabled = config.debugEnabled;
15
+ if (config.testMode !== undefined) out.testMode = config.testMode;
16
+ return out;
17
+ }
18
+
19
+ export function normalizeSize(size: string | undefined): string {
20
+ if (!size) return '';
21
+ return size
22
+ .split(',')
23
+ .map((s) => s.trim())
24
+ .filter((s) => s.length > 0)
25
+ .join(',');
26
+ }
27
+
28
+ export function coerceAdUnitId(adUnitIdentifier: string): string {
29
+ return String(adUnitIdentifier);
30
+ }
package/src/index.tsx ADDED
@@ -0,0 +1,68 @@
1
+ import type { StyleProp, ViewStyle } from 'react-native';
2
+ import NativeEzoicAds, { type EzoicConfig } from './NativeEzoicAds';
3
+ import EzoicBannerNative from './EzoicBannerViewNativeComponent';
4
+ import { coerceAdUnitId, normalizeConfig, normalizeSize } from './helpers';
5
+
6
+ export type { EzoicConfig };
7
+
8
+ export const EzoicAds = {
9
+ initialize(config: EzoicConfig): Promise<void> {
10
+ return NativeEzoicAds.initialize(normalizeConfig(config));
11
+ },
12
+ setGDPRConsent(applies: boolean, consentString?: string): void {
13
+ NativeEzoicAds.setGDPRConsent(applies, consentString);
14
+ },
15
+ setGPPConsent(gppString?: string, sectionIds?: string): void {
16
+ NativeEzoicAds.setGPPConsent(gppString, sectionIds);
17
+ },
18
+ setSubjectToCOPPA(value: boolean): void {
19
+ NativeEzoicAds.setSubjectToCOPPA(value);
20
+ },
21
+ trackPageview(): Promise<boolean> {
22
+ return NativeEzoicAds.trackPageview();
23
+ },
24
+ };
25
+
26
+ export interface EzoicBannerError {
27
+ message: string;
28
+ code: number;
29
+ }
30
+
31
+ export interface EzoicBannerViewProps {
32
+ adUnitIdentifier: string;
33
+ size?: string;
34
+ style?: StyleProp<ViewStyle>;
35
+ onLoad?: () => void;
36
+ onError?: (error: EzoicBannerError) => void;
37
+ onImpression?: () => void;
38
+ onClick?: () => void;
39
+ onOpen?: () => void;
40
+ onClose?: () => void;
41
+ }
42
+
43
+ export function EzoicBannerView(props: EzoicBannerViewProps) {
44
+ const {
45
+ adUnitIdentifier,
46
+ size,
47
+ onLoad,
48
+ onError,
49
+ onImpression,
50
+ onClick,
51
+ onOpen,
52
+ onClose,
53
+ ...rest
54
+ } = props;
55
+ return (
56
+ <EzoicBannerNative
57
+ {...rest}
58
+ adUnitIdentifier={coerceAdUnitId(adUnitIdentifier)}
59
+ size={normalizeSize(size)}
60
+ onLoad={onLoad ? () => onLoad() : undefined}
61
+ onError={onError ? (e) => onError(e.nativeEvent) : undefined}
62
+ onImpression={onImpression ? () => onImpression() : undefined}
63
+ onAdClick={onClick ? () => onClick() : undefined}
64
+ onOpen={onOpen ? () => onOpen() : undefined}
65
+ onClose={onClose ? () => onClose() : undefined}
66
+ />
67
+ );
68
+ }