Skip to content

Commit cdb4ce8

Browse files
committed
improved ads
1 parent 2098ba0 commit cdb4ce8

File tree

5 files changed

+134
-109
lines changed

5 files changed

+134
-109
lines changed

src/components/elements/AdUnit.astro

Lines changed: 0 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ interface Props {
88
adLayout?: string;
99
adLayoutKey?: string;
1010
className?: string;
11-
refreshInterval?: number; // in seconds, default 5
1211
}
1312
1413
const {
@@ -18,7 +17,6 @@ const {
1817
adLayout,
1918
adLayoutKey,
2019
className = "",
21-
refreshInterval = 5,
2220
} = Astro.props;
2321
2422
// Generate unique ID for this ad instance
@@ -82,72 +80,6 @@ const adId = `ad-${adType}-${adSlot}-${Math.random().toString(36).substr(2, 9)}`
8280
(adsbygoogle = window.adsbygoogle || []).push({});
8381
</script>
8482

85-
<script is:inline define:vars={{ adId, refreshInterval }}>
86-
// Ad refresh functionality
87-
(function() {
88-
const adContainer = document.getElementById(adId);
89-
if (!adContainer) return;
90-
91-
let refreshTimer;
92-
let refreshCount = 0;
93-
const maxRefreshes = 20; // Limit refreshes to prevent abuse
94-
95-
function refreshAd() {
96-
const adElement = adContainer.querySelector('.adsbygoogle');
97-
if (!adElement) return;
98-
99-
// Check if ad is loaded and visible
100-
const adStatus = adElement.getAttribute('data-ad-status');
101-
const isVisible = adContainer.offsetWidth > 0 && adContainer.offsetHeight > 0;
102-
103-
if (adStatus === 'filled' && isVisible && refreshCount < maxRefreshes) {
104-
try {
105-
// Clear existing ad
106-
adElement.innerHTML = '';
107-
108-
// Re-push the ad
109-
(adsbygoogle = window.adsbygoogle || []).push({});
110-
111-
refreshCount++;
112-
console.log(`Ad refreshed (${refreshCount}/${maxRefreshes}): ${adId}`);
113-
} catch (error) {
114-
console.warn('Ad refresh failed:', error);
115-
}
116-
}
117-
}
118-
119-
// Start refreshing after initial load
120-
function startRefreshing() {
121-
if (refreshTimer) clearInterval(refreshTimer);
122-
123-
refreshTimer = setInterval(refreshAd, refreshInterval * 1000);
124-
125-
// Also refresh on visibility change (tab focus, etc.)
126-
document.addEventListener('visibilitychange', function() {
127-
if (!document.hidden) {
128-
setTimeout(refreshAd, 1000); // Small delay after tab becomes visible
129-
}
130-
});
131-
}
132-
133-
// Wait for ad to load before starting refresh cycle
134-
const checkAdLoaded = setInterval(function() {
135-
const adElement = adContainer.querySelector('.adsbygoogle');
136-
if (adElement && adElement.getAttribute('data-ad-status') === 'filled') {
137-
clearInterval(checkAdLoaded);
138-
setTimeout(startRefreshing, 2000); // Start refreshing 2 seconds after initial load
139-
}
140-
}, 500);
141-
142-
// Cleanup on page unload
143-
window.addEventListener('beforeunload', function() {
144-
if (refreshTimer) {
145-
clearInterval(refreshTimer);
146-
}
147-
});
148-
})();
149-
</script>
150-
15183
<style>
15284
.ad-container {
15385
min-height: 0 !important;

src/layouts/content.astro

Lines changed: 77 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,88 @@
11
---
22
// Content layout component
3+
import AdUnit from "@/components/elements/AdUnit.astro";
4+
5+
interface Props {
6+
showAds?: boolean;
7+
}
8+
9+
const { showAds = false } = Astro.props;
10+
const googleAdsenseClientId = import.meta.env.PUBLIC_GOOGLE_ADSENSE_CLIENT_ID;
311
---
412

513
<article
614
class="prose md:prose-lg py-8 container prose-img:border prose-img:mx-auto prose-img:border-base-200 prose-img:rounded-lg prose-p:break-words prose-a:break-all prose-pre:break-words prose-pre:cursor-text prose-code:break-words prose-code:whitespace-pre-wrap"
715
data-pagefind-body
816
>
917
<div id="article-content">
10-
<slot />
18+
{showAds ? (
19+
<slot name="content-with-ads" />
20+
) : (
21+
<slot />
22+
)}
1123
</div>
1224
</article>
25+
26+
{showAds && (
27+
<script define:vars={{ googleAdsenseClientId }}>
28+
function injectAdsIntoContent() {
29+
const articleContent = document.getElementById('article-content');
30+
if (!articleContent) return;
31+
32+
// Get all paragraphs in the article content
33+
const paragraphs = articleContent.querySelectorAll('p');
34+
35+
if (paragraphs.length < 4) return; // Don't inject ads if content is too short
36+
37+
let adCount = 0;
38+
const maxAds = 3; // Maximum number of ads to inject
39+
40+
// Convert NodeList to Array and filter out paragraphs that are inside other elements
41+
const eligibleParagraphs = Array.from(paragraphs).filter(p => {
42+
// Skip paragraphs that are inside blockquotes, lists, or other containers
43+
return !p.closest('blockquote, ul, ol, pre, .ad-container');
44+
});
45+
46+
// Shuffle and select random positions for ads
47+
const adPositions = [];
48+
for (let i = 2; i < eligibleParagraphs.length - 1; i++) {
49+
if (Math.random() > 0.6 && adCount < maxAds) { // 40% chance
50+
adPositions.push(i);
51+
adCount++;
52+
}
53+
}
54+
55+
// Sort positions in reverse order to avoid index shifting
56+
adPositions.sort((a, b) => b - a);
57+
58+
// Inject ads at selected positions
59+
adPositions.forEach(pos => {
60+
const targetParagraph = eligibleParagraphs[pos];
61+
if (targetParagraph && targetParagraph.parentNode) {
62+
const adContainer = document.createElement('div');
63+
adContainer.className = 'my-6 flex justify-center ad-container';
64+
adContainer.innerHTML = `
65+
<div class="w-full max-w-sm">
66+
<ins class="adsbygoogle"
67+
style="display:block"
68+
data-ad-client="${googleAdsenseClientId}"
69+
data-ad-slot="2308296961"
70+
data-ad-format="auto"
71+
data-full-width-responsive="true"></ins>
72+
<script>(adsbygoogle = window.adsbygoogle || []).push({});<\/script>
73+
</div>
74+
`;
75+
76+
targetParagraph.parentNode.insertBefore(adContainer, targetParagraph.nextSibling);
77+
}
78+
});
79+
}
80+
81+
// Run ad injection after content is loaded
82+
if (document.readyState === 'loading') {
83+
document.addEventListener('DOMContentLoaded', injectAdsIntoContent);
84+
} else {
85+
injectAdsIntoContent();
86+
}
87+
</script>
88+
)}

src/pages/articles/[year]/[month]/[day]/[slug].astro

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,8 +100,7 @@ if (recommended.length < 3) {
100100
</div>
101101
</div>
102102
<ContentLayout showAds={true}>
103-
<Content />
104-
<AdUnit adSlot="2308296961" adLayout="in-article" adFormat="fluid" />
103+
<Content slot="content-with-ads" />
105104
</ContentLayout>
106105

107106
{
@@ -153,6 +152,15 @@ if (recommended.length < 3) {
153152
Edit this article
154153
</a>
155154
</div>
155+
<!-- Vertical Ad below Edit Button -->
156+
<div class="mt-4">
157+
<AdUnit
158+
adType="display"
159+
adSlot="1038118330"
160+
adFormat="auto"
161+
className="w-full"
162+
/>
163+
</div>
156164
</div>
157165
</div>
158166
</div>

src/pages/categories/index.astro

Lines changed: 46 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { getEntry } from "astro:content";
44
import { categoriesHandler } from "@/lib/handlers/categories";
55
import NewsCard from "@/components/cards/newsCard.astro";
66
import ArrowRight02 from "@/assets/svgs/arrow-right-02.astro";
7+
import AdUnit from "@/components/elements/AdUnit.astro";
78
89
const entry = await getEntry("views", "categories");
910
@@ -19,41 +20,56 @@ const articles = categoriesHandler.allCategoriesWithLatestArticles();
1920
<ListLayout header={"All Categories"} entry={entry}>
2021
<ul class="w-full space-y-8 my-6">
2122
{
22-
articles.map((category) => {
23+
articles.map((category, categoryIndex) => {
2324
const { path, title, latestArticles } = category.data;
2425
const articleCount = category.data.count;
2526
return (
26-
<div class="flex flex-col items-start gap-4">
27-
<div class="flex items-center w-full justify-between gap-2 border-b border-accent/30">
28-
<h2 class="text-xl inline-flex items-center">
29-
{title}{" "}
30-
<span class="text-xs font-sans ml-2 text-primary">
31-
({articleCount} Articles)
32-
</span>
33-
</h2>
34-
<a
35-
href={`/categories/${path}/1`}
36-
class="group flex text-sm items-center gap-1 hover:gap-2 transition-all duration-200"
37-
>
38-
See All
39-
<span class="transform group-hover:translate-x-1 transition-transform duration-200">
40-
<ArrowRight02 size="16" />
41-
</span>
42-
</a>
43-
</div>
44-
<div class="snap-x">
45-
{/* {latestArticles.slice(0, 6).map((article, index) => (
46-
<NewsCard article={article} index={index} />
47-
))} */}
48-
<div class="flex overflow-x-auto pb-4 space-x-4 snap-x snap-proximity">
49-
{latestArticles.slice(0, 6).map((article, index) => (
50-
<div class="snap-start flex-none lg:flex-initial">
51-
<NewsCard article={article} index={index} />
52-
</div>
53-
))}
27+
<>
28+
<div class="flex flex-col items-start gap-4">
29+
<div class="flex items-center w-full justify-between gap-2 border-b border-accent/30">
30+
<h2 class="text-xl inline-flex items-center">
31+
{title}{" "}
32+
<span class="text-xs font-sans ml-2 text-primary">
33+
({articleCount} Articles)
34+
</span>
35+
</h2>
36+
<a
37+
href={`/categories/${path}/1`}
38+
class="group flex text-sm items-center gap-1 hover:gap-2 transition-all duration-200"
39+
>
40+
See All
41+
<span class="transform group-hover:translate-x-1 transition-transform duration-200">
42+
<ArrowRight02 size="16" />
43+
</span>
44+
</a>
45+
</div>
46+
<div class="snap-x">
47+
{/* {latestArticles.slice(0, 6).map((article, index) => (
48+
<NewsCard article={article} index={index} />
49+
))} */}
50+
<div class="flex overflow-x-auto pb-4 space-x-4 snap-x snap-proximity">
51+
{latestArticles.slice(0, 6).map((article, index) => (
52+
<div class="snap-start flex-none lg:flex-initial">
53+
<NewsCard article={article} index={index} />
54+
</div>
55+
))}
56+
</div>
5457
</div>
5558
</div>
56-
</div>
59+
{/* Insert horizontal ad after every 3rd category, but not after the last category */}
60+
{categoryIndex > 0 &&
61+
(categoryIndex + 1) % 3 === 0 &&
62+
categoryIndex !== articles.length - 1 && (
63+
<li class="my-8 flex justify-center">
64+
<AdUnit
65+
adType="fluid-layout"
66+
adSlot="5304666400"
67+
adLayoutKey="-fb+5w+4e-db+86"
68+
className="w-full max-w-4xl"
69+
/>
70+
</li>
71+
)}
72+
</>
5773
);
5874
})
5975
}

src/pages/index.astro

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@ if (!entry) {
3535
adSlot="1038118330"
3636
adFormat="auto"
3737
className="w-full"
38-
refreshInterval={5}
3938
/>
4039
</div>
4140
</aside>
@@ -46,12 +45,7 @@ if (!entry) {
4645
<LatestNews />
4746

4847
<!-- Autorelaxed Ad -->
49-
<AdUnit
50-
adType="autorelaxed"
51-
adSlot="9560154927"
52-
className="my-8"
53-
refreshInterval={5}
54-
/>
48+
<AdUnit adType="autorelaxed" adSlot="9560154927" className="my-8" />
5549

5650
<Authors />
5751
</main>
@@ -64,7 +58,6 @@ if (!entry) {
6458
adSlot="1038118330"
6559
adFormat="auto"
6660
className="w-full"
67-
refreshInterval={5}
6861
/>
6962
</div>
7063
</aside>

0 commit comments

Comments
 (0)