@cardsjd/portal 0.1.13 → 0.1.15

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.
@@ -77,8 +77,8 @@ export class AdMobPortal extends BasePortal {
77
77
  AdMob.addListener(InterstitialAdPluginEvents.Loaded, () => {
78
78
  this.isInterstitialAdReady = true;
79
79
  });
80
- AdMob.addListener(InterstitialAdPluginEvents.Showed, () => {
81
- this.isInterstitialAdReady = false;
80
+ AdMob.addListener(InterstitialAdPluginEvents.Showed, () => {
81
+ this.isInterstitialAdReady = false;
82
82
  if (this.onAdOpened) {
83
83
  this.onAdOpened({
84
84
  adType: 'interstitial',
@@ -155,13 +155,19 @@ export class AdMobPortal extends BasePortal {
155
155
  }
156
156
 
157
157
  async showInterstitialAd() {
158
- if (!this.isAdLoaded()) {
159
- await this.loadInterstitialAd();
160
- return; // no auto show
158
+ if (!this.isAdLoaded()) {
159
+ await this.loadInterstitialAd();
160
+ return false; // no auto show
161
161
  }
162
162
 
163
163
  this.isInterstitialAdReady = false;
164
- return AdMob.showInterstitial();
164
+ try {
165
+ await AdMob.showInterstitial();
166
+ } catch (error) {
167
+ console.error('Interstitial ad failed to show', error);
168
+ }
169
+
170
+ return true;
165
171
  }
166
172
 
167
173
  async loadRewardedAd() {
package/lib/BasePortal.js CHANGED
@@ -26,11 +26,12 @@ export class BasePortal {
26
26
 
27
27
  async getFriends() { }
28
28
 
29
- async setupAds() { }
29
+ async setupAds() { }
30
30
 
31
31
  async loadInterstitialAd(_force) { }
32
32
 
33
- async showInterstitialAd() { }
33
+ // Returns true if a display was attempted, false if only loading or unavailable.
34
+ async showInterstitialAd() { return true; }
34
35
 
35
36
  loadRewardedAd(_onLoaded) { }
36
37
 
@@ -42,15 +43,15 @@ export class BasePortal {
42
43
 
43
44
  isAdLoaded() { }
44
45
 
45
- isRewardedAdLoaded() { }
46
-
47
- isPrivacyOptionsRequired() {
48
- return false;
49
- }
50
-
51
- async showPrivacyOptions() { }
52
-
53
- logError(_errorCode) { }
46
+ isRewardedAdLoaded() { }
47
+
48
+ isPrivacyOptionsRequired() {
49
+ return false;
50
+ }
51
+
52
+ async showPrivacyOptions() { }
53
+
54
+ logError(_errorCode) { }
54
55
 
55
56
  isErrorState() { }
56
57
 
@@ -96,8 +97,12 @@ export class BasePortal {
96
97
  console.log('readyToShowInterstitialAd: ' + readyToShowAd + ' : ' + secondsSinceLastAd + ' of ' + delayBetweenAds);
97
98
 
98
99
  // show ad or just load ad (not load and show)
99
- if (readyToShowAd) {
100
- await this.showInterstitialAd();
100
+ if (readyToShowAd) {
101
+ // showInterstitialAd returns true if the ad was shown or the show attempt failed;
102
+ // false means it only loaded or skipped the ad without attempting to show it.
103
+ if (await this.showInterstitialAd()) {
104
+ this.lastShownInterstitial = Date.now();
105
+ }
101
106
  } else {
102
107
  await this.loadInterstitialAd();
103
108
  }
@@ -299,7 +299,13 @@ export class CrazyGamesPortal extends BasePortal {
299
299
  },
300
300
  };
301
301
 
302
- globalThis.CrazyGames.SDK.ad.requestAd('midgame', callbacks);
302
+ try {
303
+ await globalThis.CrazyGames.SDK.ad.requestAd('midgame', callbacks);
304
+ } catch (error) {
305
+ console.error('Interstitial ad failed to show', error);
306
+ }
307
+
308
+ return true;
303
309
  }
304
310
 
305
311
  isAdLoaded() {
@@ -1,4 +1,4 @@
1
- import { BasePortal } from './BasePortal';
1
+ import { BasePortal } from './BasePortal';
2
2
  import { FBInstantGame } from '@cardsjd/fbinstantgame';
3
3
 
4
4
  export class FacebookPortal extends BasePortal {
@@ -32,20 +32,20 @@ export class FacebookPortal extends BasePortal {
32
32
 
33
33
  async load() {
34
34
  const fbUserdata = await this.fBInstantGame.loadData();
35
- const fbProfile = await this.fBInstantGame.getProfile();
36
- const data = {};
37
- data.userdata = fbUserdata;
38
- data.user = fbProfile ? {
39
- facebookId: fbProfile.facebookId ?? fbProfile.id,
40
- name: fbProfile.name,
41
- avatar: fbProfile.avatar ?? fbProfile.pic,
42
- locale: fbProfile.locale,
43
- } : null;
35
+ const fbProfile = await this.fBInstantGame.getProfile();
36
+ const data = {};
37
+ data.userdata = fbUserdata;
38
+ data.user = fbProfile ? {
39
+ facebookId: fbProfile.facebookId ?? fbProfile.id,
40
+ name: fbProfile.name,
41
+ avatar: fbProfile.avatar ?? fbProfile.pic,
42
+ locale: fbProfile.locale,
43
+ } : null;
44
44
  return data;
45
45
  }
46
46
 
47
- async save(data, forceSave) {
48
- this.fBInstantGame.saveData(data, forceSave).catch(function () { });
47
+ async save(data, forceSave) {
48
+ this.fBInstantGame.saveData(data, forceSave).catch(function () { });
49
49
  }
50
50
 
51
51
  gameStart() {
@@ -65,10 +65,10 @@ export class FacebookPortal extends BasePortal {
65
65
 
66
66
  this.subscribeBot();
67
67
  }
68
- createShortCut() {
69
- this.portal?.createShortCut?.();
70
- }
71
- async subscribeBot() {
68
+ createShortCut() {
69
+ this.portal?.createShortCut?.();
70
+ }
71
+ async subscribeBot() {
72
72
  await this.fBInstantGame.subscribeBot();
73
73
  }
74
74
 
@@ -111,7 +111,7 @@ export class FacebookPortal extends BasePortal {
111
111
 
112
112
  // ----- Ad methods -----
113
113
 
114
- async setupAds() {
114
+ async setupAds() {
115
115
  console.log('FB_Ads.setup');
116
116
 
117
117
  if (typeof FBInstant === 'undefined' || !globalThis.FBInstant) {
@@ -188,7 +188,7 @@ export class FacebookPortal extends BasePortal {
188
188
 
189
189
  this._isAdLoading = true;
190
190
 
191
- const interstitialAdId = this.appConfig?.interstitialAdId;
191
+ const interstitialAdId = this.appConfig?.interstitialAdId;
192
192
 
193
193
  console.log('FB_Ads.getInterstitialAdAsync start: ' + interstitialAdId);
194
194
  if (!this.isApiSupported('getInterstitialAdAsync')) {
@@ -249,6 +249,7 @@ export class FacebookPortal extends BasePortal {
249
249
 
250
250
  if (!isAdLoaded) {
251
251
  this.loadInterstitialAd();
252
+ return false;
252
253
  }
253
254
 
254
255
  if (isAdLoaded) {
@@ -257,7 +258,7 @@ export class FacebookPortal extends BasePortal {
257
258
  return false;
258
259
  }
259
260
 
260
- this.preloadedInterstitial.showAsync()
261
+ return Promise.resolve().then(() => this.preloadedInterstitial.showAsync())
261
262
  .then(() => {
262
263
  // Perform post-ad success operation
263
264
  console.log('Interstitial ad finished successfully');
@@ -273,7 +274,7 @@ export class FacebookPortal extends BasePortal {
273
274
  this.logError(err.code);
274
275
  console.error('interstitialAd Error: ' + err.message + ' ' + err.code);
275
276
 
276
- });
277
+ }).then(() => true);
277
278
  }
278
279
 
279
280
  }
@@ -290,7 +291,7 @@ export class FacebookPortal extends BasePortal {
290
291
  console.log('FBInstant plugin not ready'); return false;
291
292
  }
292
293
 
293
- const interstitialAdId = this.appConfig?.interstitialAdId;
294
+ const interstitialAdId = this.appConfig?.interstitialAdId;
294
295
  if (!this.isApiSupported('getInterstitialAdAsync')) {
295
296
  this.logError('CLIENT_UNSUPPORTED_OPERATION');
296
297
  console.warn('FBInstant.getInterstitialAdAsync is not supported on this client');
@@ -69,7 +69,13 @@ export class GameDistribution extends BasePortal {
69
69
  return false;
70
70
  }
71
71
 
72
- return globalThis.gdsdk.showAd(AdType.Interstitial);
72
+ try {
73
+ await globalThis.gdsdk.showAd(AdType.Interstitial);
74
+ } catch (error) {
75
+ console.error('Interstitial ad failed to show', error);
76
+ }
77
+
78
+ return true;
73
79
  }
74
80
 
75
81
  isAdLoaded() {
@@ -33,6 +33,7 @@ export class NextGenAdMobPortal extends BasePortal {
33
33
  this._consentInfoUpdated = false;
34
34
  this._consentGathered = false;
35
35
  this._canRequestAds = false;
36
+ this._limitedAdsFallback = false;
36
37
  this._privacyOptionsRequired = false;
37
38
  this.isTesting = false;
38
39
  }
@@ -85,21 +86,55 @@ export class NextGenAdMobPortal extends BasePortal {
85
86
  async showPrivacyOptions() {
86
87
  await this.loadUmp();
87
88
  const consentInfo = await this._umpModule.showPrivacyOptions();
89
+ if (consentInfo.canRequestAds === true) {
90
+ this._limitedAdsFallback = false;
91
+ }
92
+
88
93
  this.setConsentInfo(consentInfo);
89
94
  return consentInfo;
90
95
  }
91
96
 
97
+ async requestConsent(method) {
98
+ try {
99
+ await this.loadUmp();
100
+ return await this._umpModule[method]();
101
+ } catch (error) {
102
+ // UMP may still allow ads using consent from a previous session.
103
+ let consentInfo;
104
+ try {
105
+ consentInfo = await this._umpModule.getConsentInfo();
106
+ } catch (statusError) {
107
+ console.warn('Unable to read UMP consent status:', statusError);
108
+ }
109
+
110
+ if (consentInfo?.canRequestAds === true) {
111
+ console.warn('UMP consent request failed; using existing consent:', error);
112
+ return consentInfo;
113
+ }
114
+
115
+ // Set Google's native limited-ad signal before allowing any ad requests.
116
+ await this.loadUmp();
117
+ await this._umpModule.enableLimitedAds();
118
+ this._limitedAdsFallback = true;
119
+ this._consentGathered = true;
120
+ console.warn('UMP consent request failed; requesting limited ads:', error);
121
+ return {
122
+ canRequestAds: true,
123
+ formShown: false,
124
+ privacyOptionsRequired: consentInfo?.privacyOptionsRequired ?? this._privacyOptionsRequired,
125
+ };
126
+ }
127
+ }
128
+
92
129
  async updateConsentInfo() {
93
- await this.loadUmp();
94
- const consentInfo = await this._umpModule.updateConsentInfo();
130
+ const consentInfo = await this.requestConsent('updateConsentInfo');
95
131
  this._consentInfoUpdated = true;
96
132
  this.setConsentInfo(consentInfo);
97
133
  return consentInfo;
98
134
  }
99
135
 
100
136
  async gatherConsent() {
101
- await this.loadUmp();
102
- const consentInfo = await this._umpModule.gatherConsent();
137
+ const consentInfo = await this.requestConsent('gatherConsent');
103
138
  this._consentInfoUpdated = true;
104
139
  this._consentGathered = true;
105
140
  this.setConsentInfo(consentInfo);
@@ -169,7 +204,7 @@ export class NextGenAdMobPortal extends BasePortal {
169
204
  };
170
205
  }
171
206
 
172
- const trackingPromptShown = await this.requestTrackingAuthorization(consentInfo);
207
+ const trackingPromptShown = !this._limitedAdsFallback && await this.requestTrackingAuthorization(consentInfo);
173
208
  const promptShown = consentInfo?.formShown === true || trackingPromptShown;
174
209
 
175
210
  if (consentInfo.canRequestAds !== true) {
@@ -195,7 +230,7 @@ export class NextGenAdMobPortal extends BasePortal {
195
230
  await this.setupAds();
196
231
  }
197
232
 
198
- if (!this._canRequestAds || !await this.canStartAdsWithoutPrompt()) {
233
+ if (!this._canRequestAds || (!this._limitedAdsFallback && !await this.canStartAdsWithoutPrompt())) {
199
234
  return false;
200
235
  }
201
236
 
@@ -351,7 +386,7 @@ export class NextGenAdMobPortal extends BasePortal {
351
386
  async showInterstitialAd() {
352
387
  const setup = await this.ensureAdsReady();
353
388
  if (!setup.canRequestAds || setup.promptShown) {
354
- return;
389
+ return false;
355
390
  }
356
391
 
357
392
  if (!this.isAdLoaded()) {
@@ -361,12 +396,18 @@ export class NextGenAdMobPortal extends BasePortal {
361
396
  })]);
362
397
  clearTimeout(timeoutId);
363
398
  if (!this.isAdLoaded()) {
364
- return;
399
+ return false;
365
400
  }
366
401
  }
367
402
 
368
403
  this.isInterstitialAdReady = false;
369
- return this._interstitialAd.show();
404
+ try {
405
+ await this._interstitialAd.show();
406
+ } catch (error) {
407
+ console.error('Interstitial ad failed to show', error);
408
+ }
409
+
410
+ return true;
370
411
  }
371
412
 
372
413
  async loadRewardedAd() {
package/lib/PokiPortal.js CHANGED
@@ -221,18 +221,18 @@ export class PokiPortal extends BasePortal {
221
221
  });
222
222
  }
223
223
 
224
- if (typeof this.onAdClosed === 'function') {
225
- this.onAdClosed({
226
- adType,
227
- adProvider,
228
- });
229
- }
230
-
231
- return false;
232
- }
233
- }
234
-
235
- isAdLoaded() {
224
+ if (typeof this.onAdClosed === 'function') {
225
+ this.onAdClosed({
226
+ adType,
227
+ adProvider,
228
+ });
229
+ }
230
+
231
+ return true;
232
+ }
233
+ }
234
+
235
+ isAdLoaded() {
236
236
  return this.isReady();
237
237
  }
238
238
 
package/lib/WebPortal.js CHANGED
@@ -125,22 +125,22 @@ export class WebPortal extends BasePortal {
125
125
  }
126
126
 
127
127
  showInterstitialAd() {
128
- console.log('GoogleH5.showAd');
129
-
130
- if (typeof adBreak === 'undefined' || !globalThis.adBreak) {
131
- console.log('GoogleH5 adBreak plugin not ready'); return;
132
- }
133
-
134
- if (!this.isSetup) {
135
- console.log('GoogleH5.showAd - isSetup is false');
136
- return;
128
+ console.log('GoogleH5.showAd');
129
+
130
+ if (typeof adBreak === 'undefined' || !globalThis.adBreak) {
131
+ console.log('GoogleH5 adBreak plugin not ready'); return false;
137
132
  }
138
133
 
139
- globalThis.adBreak({
134
+ if (!this.isSetup) {
135
+ console.log('GoogleH5.showAd - isSetup is false');
136
+ return false;
137
+ }
138
+
139
+ return Promise.resolve().then(() => globalThis.adBreak({
140
140
  type: 'next', // The type of this placement (required)
141
- name: 'post_game', // A descriptive name for this placement
142
- beforeAd: () => {
143
- if (this.onAdOpened) {
141
+ name: 'post_game', // A descriptive name for this placement
142
+ beforeAd: () => {
143
+ if (this.onAdOpened) {
144
144
  this.onAdOpened({
145
145
  adType: 'interstitial',
146
146
  adProvider: this.adProviderName,
@@ -155,10 +155,12 @@ export class WebPortal extends BasePortal {
155
155
  });
156
156
  }
157
157
  },
158
- adBreakDone: (placementInfo) => {
159
- console.log('placementInfo', placementInfo);
160
- },
161
- });
158
+ adBreakDone: (placementInfo) => {
159
+ console.log('placementInfo', placementInfo);
160
+ },
161
+ })).catch(error => {
162
+ console.error('Interstitial ad failed to show', error);
163
+ }).then(() => true);
162
164
  }
163
165
 
164
166
  isAdLoaded() {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@cardsjd/portal",
3
3
  "private": false,
4
- "version": "0.1.13",
4
+ "version": "0.1.15",
5
5
  "type": "module",
6
6
  "main": "lib/index.js",
7
7
  "publishConfig": {