nodebb-plugin-ezoic-infinite 1.5.77 → 1.5.78

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 (2) hide show
  1. package/package.json +1 -1
  2. package/public/client.js +36 -8
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nodebb-plugin-ezoic-infinite",
3
- "version": "1.5.77",
3
+ "version": "1.5.78",
4
4
  "description": "Production-ready Ezoic infinite ads integration for NodeBB 4.x",
5
5
  "main": "library.js",
6
6
  "license": "MIT",
package/public/client.js CHANGED
@@ -10,7 +10,10 @@
10
10
  const POOL_ID = 'nodebb-ezoic-placeholder-pool';
11
11
 
12
12
  // Smoothness caps
13
- const MAX_INSERTS_PER_RUN = 3;
13
+ // Limit how many placements we inject per scan pass.
14
+ // Too low = you end up with only a handful of placeholders after ajaxify.
15
+ // Too high = jank on very long pages.
16
+ const MAX_INSERTS_PER_RUN = 8;
14
17
 
15
18
  // Keep empty (unfilled) wraps alive for a while. Topics/messages can fill late (auction/CMP).
16
19
  // Pruning too early makes ads look like they "disappear" while scrolling.
@@ -586,12 +589,11 @@ function globalGapFixInit() {
586
589
  if (!state.allPosts.length) state.allPosts = parsePool(cfg.messagePlaceholderIds);
587
590
  if (!state.allCategories.length) state.allCategories = parsePool(cfg.categoryPlaceholderIds);
588
591
 
589
- // Create placeholders up-front in an offscreen pool.
590
- // Ezoic may attempt to define/show ids during load; if they don't exist yet,
591
- // it can spam errors and sometimes short-circuit. Pooling keeps ids existing without layout.
592
- primePlaceholderPool(state.allTopics);
593
- primePlaceholderPool(state.allPosts);
594
- primePlaceholderPool(state.allCategories);
592
+ // IMPORTANT:
593
+ // We do NOT prime a DOM pool anymore.
594
+ // Keeping placeholders connected (even offscreen) can lead Ezoic/GPT to
595
+ // pre-define slots, which then causes "Placeholder Id X has already been defined".
596
+ // Instead, we create the placeholder element only when we actually inject its wrapper.
595
597
  }
596
598
 
597
599
  // ---------------- insertion primitives ----------------
@@ -908,6 +910,16 @@ function globalGapFixInit() {
908
910
  const ph = document.getElementById(`${PLACEHOLDER_PREFIX}${id}`);
909
911
  if (!ph || !ph.isConnected) return;
910
912
 
913
+ // If the placeholder already has creative, avoid re-showing.
914
+ // Re-showing is a common source of "Placeholder Id X has already been defined".
915
+ try {
916
+ if (ph.querySelector && ph.querySelector('iframe, ins, img, video, [data-google-container-id]')) {
917
+ clearTimeout(hardTimer);
918
+ release();
919
+ return;
920
+ }
921
+ } catch (e) {}
922
+
911
923
  const t = now();
912
924
  const last = state.lastShowById.get(id) || 0;
913
925
  if (t - last < 900) return;
@@ -1245,13 +1257,29 @@ function globalGapFixInit() {
1245
1257
  requestBurst();
1246
1258
  });
1247
1259
 
1260
+ // Some setups populate content in multiple phases; ensure we re-scan.
1261
+ $(window).on('action:ajaxify.contentLoaded.ezoicInfinite', () => {
1262
+ if (isBlocked()) return;
1263
+ requestBurst();
1264
+ });
1265
+
1248
1266
  $(window).on(
1249
- 'action:posts.loaded.ezoicInfinite action:topics.loaded.ezoicInfinite action:category.loaded.ezoicInfinite action:topic.loaded.ezoicInfinite',
1267
+ 'action:posts.loaded.ezoicInfinite action:topics.loaded.ezoicInfinite action:categories.loaded.ezoicInfinite action:category.loaded.ezoicInfinite action:topic.loaded.ezoicInfinite',
1250
1268
  () => {
1251
1269
  if (isBlocked()) return;
1252
1270
  requestBurst();
1253
1271
  }
1254
1272
  );
1273
+
1274
+ // Also listen through NodeBB's AMD hooks module when available.
1275
+ try {
1276
+ require(['hooks'], (hooks) => {
1277
+ if (!hooks || typeof hooks.on !== 'function') return;
1278
+ ['action:ajaxify.end', 'action:ajaxify.contentLoaded', 'action:posts.loaded', 'action:topics.loaded', 'action:categories.loaded', 'action:category.loaded', 'action:topic.loaded'].forEach((ev) => {
1279
+ try { hooks.on(ev, () => { if (!isBlocked()) requestBurst(); }); } catch (e) {}
1280
+ });
1281
+ });
1282
+ } catch (e) {}
1255
1283
  }
1256
1284
 
1257
1285
  function bindScroll() {