oglasi: manj vsiljivo in bolje placano

- vse enote se zahtevajo sele ~200 px pred vstopom v vidno polje
  (IntersectionObserver); prej so se vse pushale ob nalaganju strani, tudi
  tiste globoko spodaj, ki jih uporabnik ni nikoli videl. Odlocitev o praznosti
  (3 s) tece sele od zahteve, ne od mounta.
- clanek: zgornji pas odstranjen (potiskal je naslovnico in naslov pod pregib,
  placan pa je najslabse). Prvi oglas pride sele v besedilu.
- clanek: stevilo oglasov vezano na dolzino — 2 osnovna + 1 na vsakih 5 blokov
  cez 10, strop 5. Mediana (9 blokov) ostane pri 2, dolgi clanki dobijo do 5.
  Prvi je fluid in-article, vsi nadaljnji nov InContentDisplayAd (odzivni
  display, visja kreativa).
- TopBannerAd na seznamih: odzivni namesto trdih 90 px.
- mobilni lepljivi pas: odzivni vodoravni (do 110 px) namesto trdih 320x50,
  z onAdStatus — prazen se ne izrise.
- PageSideAds: en desni 300x600 sticky z onAdStatus namesto dveh 160x600 brez
  zaznave (prazna je pustila luknjo); prikaze se od 1700 px navzgor.
- interstitial odstranjen s horoskopa (prekrivalo cez zaslon, zaklenilo scroll);
  interstitial-ad.tsx in neuporabljen parallax-ad.tsx izbrisana.

CMP ostaja nedotaknjen po dogovoru.
This commit is contained in:
Claude
2026-08-28 09:25:49 +00:00
parent 10c24d3e8c
commit db9eac20e2
6 changed files with 135 additions and 156 deletions
+15 -5
View File
@@ -9,7 +9,7 @@ import { Button } from "@/components/ui/button";
import { Skeleton } from "@/components/ui/skeleton";
import Header from "@/components/header";
import Footer from "@/components/footer";
import { InArticleAd, PageSideAds, MultiplexAd, TopBannerAd } from "@/components/adsense";
import { InArticleAd, InContentDisplayAd, PageSideAds, MultiplexAd } from "@/components/adsense";
import { useIsMobile } from "@/hooks/use-mobile";
import DOMPurify from "dompurify";
import ShareButtons from "@/components/share-buttons";
@@ -304,7 +304,8 @@ export default function ArticlePage() {
<Header />
<PageSideAds contentHalfWidth={480} />
<main className="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8 py-4">
<TopBannerAd />
{/* Zgornjega pasu na clanku namenoma ni: potiskal je naslovnico in naslov
pod pregib, placan pa je najslabse. Prvi oglas pride sele v besedilu. */}
<Link href="/">
<Button variant="ghost" size="sm" className="mb-3 gap-2" data-testid="button-back">
<ArrowLeft className="w-4 h-4" />
@@ -375,9 +376,18 @@ export default function ArticlePage() {
[&_div[style]]:flex [&_div[style]]:justify-center
[&_blockquote:not(.instagram-media)]:border-l-primary [&_blockquote:not(.instagram-media)]:bg-accent/50 [&_blockquote:not(.instagram-media)]:rounded-r-md [&_blockquote:not(.instagram-media)]:py-1
[&_.instagram-media]:!bg-transparent [&_.instagram-media]:!border-0 [&_.instagram-media]:!shadow-none [&_.instagram-media]:!p-0 [&_.instagram-media]:mx-auto`;
// Najvec dva oglasa v besedilu: po prvem odstavku in na sredini.
// Stevilo oglasov je vezano na dolzino clanka, ne fiksno na dva:
// dva osnovna, plus eden na vsakih pet blokov cez deset, strop pet.
// Prvi je fluid in-article (mehak, takoj za uvodom), vsi nadaljnji so
// navaden odzivni display - visja kreativa, mimo katere se odskrola.
const last = segments.length - 1;
const AD_AFTER = last <= 0 ? [] : (last === 1 ? [0] : [0, Math.floor(last / 2)]);
const extra = Math.min(3, Math.max(0, Math.floor((blocks.length - 10) / 5)));
const adCount = last <= 0 ? 0 : (last === 1 ? 1 : Math.min(2 + extra, last));
const AD_AFTER: number[] = [];
for (let i = 0; i < adCount; i++) {
const pos = i === 0 ? 0 : Math.round((i * last) / adCount);
if (pos < last && !AD_AFTER.includes(pos)) AD_AFTER.push(pos);
}
return (
<div ref={(el) => {
if (!el) return;
@@ -398,7 +408,7 @@ export default function ArticlePage() {
dangerouslySetInnerHTML={{ __html: html }}
data-testid={idx === 0 ? "article-content" : `article-content-${idx}`}
/>
{AD_AFTER.includes(idx) && <InArticleAd />}
{AD_AFTER.includes(idx) && (idx === AD_AFTER[0] ? <InArticleAd /> : <InContentDisplayAd />)}
</div>
))}
</div>
-2
View File
@@ -21,7 +21,6 @@ import {
} from "lucide-react";
import Header from "@/components/header";
import Footer from "@/components/footer";
import InterstitialAd from "@/components/interstitial-ad";
import { InArticleAd, PageSideAds, MultiplexAd } from "@/components/adsense";
import {
SIGNS,
@@ -385,7 +384,6 @@ export default function HoroscopePage() {
return (
<div className="min-h-screen bg-background">
<Header />
<InterstitialAd forceShow />
<PageSideAds />
<main className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-4">
<h1 className="sr-only" data-testid="text-horoscope-title">