feat(js): implement intersection observer lazy loading for adsense
- Add per-slot lazy loading with Intersection Observer API - Implement fill detection via MutationObserver and data-ad-status - Add configurable rootMargin and fillTimeout from database - Generate dynamic CSS based on lazy_loading_enabled setting - Add legacy mode fallback for browsers without IO support - Include backup of previous implementation (adsense-loader.legacy.js) - Add OpenSpec documentation with test plan (72 tests verified) Schema changes: - Add lazy_loading_enabled (boolean, default: true) - Add lazy_rootmargin (select: 0-500px, default: 200) - Add lazy_fill_timeout (select: 3000-10000ms, default: 5000) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -64,10 +64,12 @@ final class AdsensePlacementRenderer
|
||||
}
|
||||
|
||||
// 4. Generar CSS (usando CSSGeneratorService)
|
||||
$lazyEnabled = ($settings['behavior']['lazy_loading_enabled'] ?? true) === true;
|
||||
|
||||
$css = $this->cssGenerator->generate(
|
||||
".roi-ad-slot",
|
||||
[
|
||||
'display' => 'block',
|
||||
'display' => $lazyEnabled ? 'none' : 'block',
|
||||
'width' => '100%',
|
||||
'min_width' => '300px',
|
||||
'margin_top' => '1.5rem',
|
||||
@@ -76,6 +78,12 @@ final class AdsensePlacementRenderer
|
||||
]
|
||||
);
|
||||
|
||||
// CSS para slots con lazy loading que reciben contenido
|
||||
if ($lazyEnabled) {
|
||||
$css .= $this->cssGenerator->generate('.roi-ad-slot.roi-ad-filled', ['display' => 'block']);
|
||||
$css .= $this->cssGenerator->generate('.roi-ad-slot.roi-ad-empty', ['display' => 'none']);
|
||||
}
|
||||
|
||||
// 5. Generar HTML del anuncio
|
||||
$html = $this->buildAdHTML(
|
||||
$settings,
|
||||
@@ -161,6 +169,7 @@ final class AdsensePlacementRenderer
|
||||
{
|
||||
$publisherId = esc_attr($settings['content']['publisher_id'] ?? '');
|
||||
$delayEnabled = ($settings['forms']['delay_enabled'] ?? true) === true;
|
||||
$lazyEnabled = ($settings['behavior']['lazy_loading_enabled'] ?? true) === true;
|
||||
|
||||
if (empty($publisherId)) {
|
||||
return '';
|
||||
@@ -174,9 +183,10 @@ final class AdsensePlacementRenderer
|
||||
|
||||
$scriptType = $delayEnabled ? 'text/plain' : 'text/javascript';
|
||||
$dataAttr = $delayEnabled ? ' data-adsense-push' : '';
|
||||
$lazyAttr = $lazyEnabled ? ' data-ad-lazy="true"' : '';
|
||||
$locationClass = 'roi-ad-' . esc_attr(str_replace('_', '-', $location));
|
||||
|
||||
return $this->generateAdMarkup($format, $publisherId, $slotId, $locationClass, $visClasses, $scriptType, $dataAttr);
|
||||
return $this->generateAdMarkup($format, $publisherId, $slotId, $locationClass, $visClasses, $scriptType, $dataAttr, $lazyAttr);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -217,68 +227,69 @@ final class AdsensePlacementRenderer
|
||||
string $locationClass,
|
||||
string $visClasses,
|
||||
string $scriptType,
|
||||
string $dataAttr
|
||||
string $dataAttr,
|
||||
string $lazyAttr = ''
|
||||
): string {
|
||||
$allClasses = trim("{$locationClass} {$visClasses}");
|
||||
|
||||
return match($format) {
|
||||
'display' => $this->adDisplay($client, $slot, 728, 90, $allClasses, $scriptType, $dataAttr),
|
||||
'display-large' => $this->adDisplay($client, $slot, 970, 250, $allClasses, $scriptType, $dataAttr),
|
||||
'display-square' => $this->adDisplay($client, $slot, 300, 250, $allClasses, $scriptType, $dataAttr),
|
||||
'in-article' => $this->adInArticle($client, $slot, $allClasses, $scriptType, $dataAttr),
|
||||
'autorelaxed' => $this->adAutorelaxed($client, $slot, $allClasses, $scriptType, $dataAttr),
|
||||
default => $this->adAuto($client, $slot, $allClasses, $scriptType, $dataAttr),
|
||||
'display' => $this->adDisplay($client, $slot, 728, 90, $allClasses, $scriptType, $dataAttr, $lazyAttr),
|
||||
'display-large' => $this->adDisplay($client, $slot, 970, 250, $allClasses, $scriptType, $dataAttr, $lazyAttr),
|
||||
'display-square' => $this->adDisplay($client, $slot, 300, 250, $allClasses, $scriptType, $dataAttr, $lazyAttr),
|
||||
'in-article' => $this->adInArticle($client, $slot, $allClasses, $scriptType, $dataAttr, $lazyAttr),
|
||||
'autorelaxed' => $this->adAutorelaxed($client, $slot, $allClasses, $scriptType, $dataAttr, $lazyAttr),
|
||||
default => $this->adAuto($client, $slot, $allClasses, $scriptType, $dataAttr, $lazyAttr),
|
||||
};
|
||||
}
|
||||
|
||||
private function adDisplay(string $c, string $s, int $w, int $h, string $cl, string $t, string $a): string
|
||||
private function adDisplay(string $c, string $s, int $w, int $h, string $cl, string $t, string $a, string $lazy = ''): string
|
||||
{
|
||||
return sprintf(
|
||||
'<div class="roi-ad-slot %s">
|
||||
'<div class="roi-ad-slot %s"%s>
|
||||
<ins class="adsbygoogle" style="display:inline-block;width:%dpx;height:%dpx"
|
||||
data-ad-client="%s" data-ad-slot="%s"></ins>
|
||||
<script type="%s"%s>(adsbygoogle = window.adsbygoogle || []).push({});</script>
|
||||
</div>',
|
||||
esc_attr($cl), $w, $h, esc_attr($c), esc_attr($s), $t, $a
|
||||
esc_attr($cl), $lazy, $w, $h, esc_attr($c), esc_attr($s), $t, $a
|
||||
);
|
||||
}
|
||||
|
||||
private function adAuto(string $c, string $s, string $cl, string $t, string $a): string
|
||||
private function adAuto(string $c, string $s, string $cl, string $t, string $a, string $lazy = ''): string
|
||||
{
|
||||
return sprintf(
|
||||
'<div class="roi-ad-slot %s">
|
||||
'<div class="roi-ad-slot %s"%s>
|
||||
<ins class="adsbygoogle" style="display:block;min-height:250px"
|
||||
data-ad-client="%s" data-ad-slot="%s"
|
||||
data-ad-format="auto" data-full-width-responsive="true"></ins>
|
||||
<script type="%s"%s>(adsbygoogle = window.adsbygoogle || []).push({});</script>
|
||||
</div>',
|
||||
esc_attr($cl), esc_attr($c), esc_attr($s), $t, $a
|
||||
esc_attr($cl), $lazy, esc_attr($c), esc_attr($s), $t, $a
|
||||
);
|
||||
}
|
||||
|
||||
private function adInArticle(string $c, string $s, string $cl, string $t, string $a): string
|
||||
private function adInArticle(string $c, string $s, string $cl, string $t, string $a, string $lazy = ''): string
|
||||
{
|
||||
return sprintf(
|
||||
'<div class="roi-ad-slot %s">
|
||||
'<div class="roi-ad-slot %s"%s>
|
||||
<ins class="adsbygoogle" style="display:block;text-align:center;min-height:200px"
|
||||
data-ad-layout="in-article" data-ad-format="fluid"
|
||||
data-ad-client="%s" data-ad-slot="%s"></ins>
|
||||
<script type="%s"%s>(adsbygoogle = window.adsbygoogle || []).push({});</script>
|
||||
</div>',
|
||||
esc_attr($cl), esc_attr($c), esc_attr($s), $t, $a
|
||||
esc_attr($cl), $lazy, esc_attr($c), esc_attr($s), $t, $a
|
||||
);
|
||||
}
|
||||
|
||||
private function adAutorelaxed(string $c, string $s, string $cl, string $t, string $a): string
|
||||
private function adAutorelaxed(string $c, string $s, string $cl, string $t, string $a, string $lazy = ''): string
|
||||
{
|
||||
return sprintf(
|
||||
'<div class="roi-ad-slot %s">
|
||||
'<div class="roi-ad-slot %s"%s>
|
||||
<ins class="adsbygoogle" style="display:block;min-height:280px"
|
||||
data-ad-format="autorelaxed"
|
||||
data-ad-client="%s" data-ad-slot="%s"></ins>
|
||||
<script type="%s"%s>(adsbygoogle = window.adsbygoogle || []).push({});</script>
|
||||
</div>',
|
||||
esc_attr($cl), esc_attr($c), esc_attr($s), $t, $a
|
||||
esc_attr($cl), $lazy, esc_attr($c), esc_attr($s), $t, $a
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user