Keep AdSense rendering limited to anonymous visitors.

Show guest-only ad units on public pages and skip the AdSense script entirely for signed-in users.
This commit is contained in:
test
2026-09-20 14:49:34 +02:00
parent 37100ced3f
commit 17df4d0ad7
8 changed files with 135 additions and 8 deletions
+5
View File
@@ -9,6 +9,7 @@ import ArtworkTags from '../components/artwork/ArtworkTags'
import ArtworkDescription from '../components/artwork/ArtworkDescription'
import ArtworkEvolutionPanel from '../components/artwork/ArtworkEvolutionPanel'
import ArtworkComments from '../components/artwork/ArtworkComments'
import AdSenseUnit from '../components/ads/AdSenseUnit'
import ArtworkActionBar from '../components/artwork/ArtworkActionBar'
import ArtworkDetailsPanel from '../components/artwork/ArtworkDetailsPanel'
import CreatorSpotlight from '../components/artwork/CreatorSpotlight'
@@ -319,6 +320,10 @@ function publisherToGroupSummary(publisher) {
{/* Tags & categories */}
<ArtworkTags artwork={artwork} />
{!isAuthenticated ? (
<AdSenseUnit key={artwork.id} slot="4398418697" />
) : null}
{/* Comments */}
<ArtworkComments
artworkId={artwork.id}
@@ -0,0 +1,45 @@
import React, { useEffect, useRef } from 'react'
export default function AdSenseUnit({
slot,
client = 'ca-pub-6457864535683080',
format = 'auto',
className = '',
enabled = true,
}) {
const pushed = useRef(false)
useEffect(() => {
if (!enabled || !slot || pushed.current) {
return undefined
}
pushed.current = true
try {
window.adsbygoogle = window.adsbygoogle || []
window.adsbygoogle.push({})
} catch {
// AdSense may be blocked or not yet loaded (consent not granted).
}
return undefined
}, [enabled, slot])
if (!enabled || !slot) {
return null
}
return (
<div className={['flex w-full justify-center', className].filter(Boolean).join(' ')}>
<ins
className="adsbygoogle w-full max-w-3xl"
style={{ display: 'block', textAlign: 'center' }}
data-ad-client={client}
data-ad-slot={slot}
data-ad-format={format}
data-full-width-responsive="true"
/>
</div>
)
}
@@ -0,0 +1,43 @@
import React from 'react'
import { afterEach, describe, expect, it, vi } from 'vitest'
import { cleanup, render } from '@testing-library/react'
import AdSenseUnit from './AdSenseUnit'
describe('AdSenseUnit', () => {
afterEach(() => {
cleanup()
vi.restoreAllMocks()
delete window.adsbygoogle
})
it('renders the dashboard horizontal slot and pushes once', () => {
window.adsbygoogle = []
const { container } = render(<AdSenseUnit slot="8766048277" />)
const unit = container.querySelector('ins.adsbygoogle')
expect(unit).not.toBeNull()
expect(container.firstChild.className).toContain('justify-center')
expect(unit.className).toContain('max-w-3xl')
expect(unit.getAttribute('data-ad-client')).toBe('ca-pub-6457864535683080')
expect(unit.getAttribute('data-ad-slot')).toBe('8766048277')
expect(unit.getAttribute('data-ad-format')).toBe('auto')
expect(unit.getAttribute('data-full-width-responsive')).toBe('true')
expect(window.adsbygoogle).toHaveLength(1)
})
it('renders nothing without a slot', () => {
const { container } = render(<AdSenseUnit />)
expect(container.querySelector('ins.adsbygoogle')).toBeNull()
})
it('renders nothing when disabled for authenticated users', () => {
window.adsbygoogle = []
const { container } = render(<AdSenseUnit slot="8766048277" enabled={false} />)
expect(container.querySelector('ins.adsbygoogle')).toBeNull()
expect(window.adsbygoogle).toHaveLength(0)
})
})
@@ -209,6 +209,7 @@ export default function ArtworkActionBar({ artwork, stats, canonicalUrl, onStats
const [reported, setReported] = useState(false)
const [reportOpen, setReportOpen] = useState(false)
const isLoggedIn = Boolean(artwork?.viewer?.is_authenticated)
const downloadUnavailable = ['missing', 'pending'].includes(String(artwork?.download_status || '').toLowerCase())
useEffect(() => {
setFavorited(Boolean(artwork?.viewer?.is_favorited))
}, [artwork?.id, artwork?.viewer?.is_favorited])
@@ -404,7 +405,7 @@ export default function ArtworkActionBar({ artwork, stats, canonicalUrl, onStats
</button>
{/* Download button */}
<button
{!downloadUnavailable && <button
type="button"
aria-label="Download artwork"
onClick={handleDownload}
@@ -413,7 +414,7 @@ export default function ArtworkActionBar({ artwork, stats, canonicalUrl, onStats
>
<DownloadArrowIcon />
{downloading ? 'Downloading…' : 'Download'}
</button>
</button>}
</div>
{/* ── Mobile fixed bottom bar ─────────────────────────────────── */}
@@ -491,7 +492,7 @@ export default function ArtworkActionBar({ artwork, stats, canonicalUrl, onStats
<FlagIcon />
</button>
<button
{!downloadUnavailable && <button
type="button"
aria-label="Download artwork"
onClick={handleDownload}
@@ -500,7 +501,7 @@ export default function ArtworkActionBar({ artwork, stats, canonicalUrl, onStats
>
<DownloadArrowIcon />
{downloading ? '…' : 'Download'}
</button>
</button>}
</div>
</div>
+2 -1
View File
@@ -9,13 +9,14 @@
Renders nothing when:
- GOOGLE_ADSENSE_PUBLISHER_ID is not set in .env
- The visitor is authenticated
- User has not given consent (handled client-side via CSS class .ads-disabled)
--}}
@php
$publisherId = config('services.google_adsense.publisher_id');
@endphp
@if($publisherId)
@if($publisherId && ! auth()->check())
<div class="ad-unit-wrapper {{ $attributes->get('class', '') }}">
<ins class="adsbygoogle"
style="display:block"
+6 -2
View File
@@ -261,8 +261,8 @@
@inertiaHead
@endif
@if(config('services.google_adsense.publisher_id'))
{{-- Google AdSense — consent-gated loader --}}
@if(auth()->guest() && config('services.google_adsense.publisher_id'))
{{-- Google AdSense — guests only, consent-gated loader --}}
{{-- Script is only injected after the user accepts all cookies. --}}
{{-- If consent was given on a previous visit it fires on page load. --}}
<script>
@@ -297,6 +297,10 @@
})();
</script>
@endif
@guest
<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-6457864535683080" crossorigin="anonymous"></script>
@endguest
</head>
@php
$authBgRoutes = [
+13 -1
View File
@@ -100,8 +100,20 @@
@include('web.home.sections.news', ['items' => $props['news'] ?? []])
@include('web.home.sections.cta', ['isLoggedIn' => true])
@else
@foreach ($guestArtworkSections as $section)
@foreach ($guestArtworkSections as $index => $section)
@include('web.home.sections.artwork-section', $section)
@if($index === 0)
{{-- Skinbase Dashboard Horizontal — guests only --}}
<div class="mt-14 flex justify-center px-4 sm:px-6 lg:px-8">
<ins class="adsbygoogle w-full max-w-3xl"
style="display:block;text-align:center"
data-ad-client="ca-pub-6457864535683080"
data-ad-slot="8766048277"
data-ad-format="auto"
data-full-width-responsive="true"></ins>
<script>(adsbygoogle = window.adsbygoogle || []).push({});</script>
</div>
@endif
@endforeach
@include('web.home.sections.collections', ['collections' => $props['collections_trending'] ?: ($props['collections_featured'] ?: ($props['collections_editorial'] ?? []))])
@include('web.home.sections.world-spotlight', ['world' => $props['world_spotlight'] ?? null])