Skip to content

Commit 66ebdda

Browse files
authored
Merge branch 'main' into brett/RND-5227-site-tabs
2 parents e9c8d86 + 0656270 commit 66ebdda

File tree

4 files changed

+132
-13
lines changed

4 files changed

+132
-13
lines changed

packages/gitbook/src/components/Ads/Ad.tsx

+12-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
'use client';
22

3+
import { SiteAds, SiteAdsStatus } from '@gitbook/api';
34
import * as React from 'react';
45

56
import { t, useLanguage } from '@/intl/client';
@@ -21,6 +22,7 @@ export function Ad({
2122
spaceId,
2223
placement,
2324
ignore,
25+
siteAdsStatus,
2426
style,
2527
mode = 'auto',
2628
}: {
@@ -29,6 +31,7 @@ export function Ad({
2931
placement: string;
3032
ignore: boolean;
3133
style?: ClassValue;
34+
siteAdsStatus?: SiteAds['status'];
3235
mode?: 'classic' | 'auto' | 'cover';
3336
}) {
3437
const containerRef = React.useRef<HTMLDivElement>(null);
@@ -70,8 +73,14 @@ export function Ad({
7073

7174
let cancelled = false;
7275

73-
const preview = new URL(window.location.href).searchParams.has('ads_preview');
76+
const previewParam = new URL(window.location.href).searchParams.get('ads_preview');
77+
const preview = !!previewParam;
7478
const realZoneId = preview ? PREVIEW_ZONE_ID : zoneId;
79+
const showPlaceholderAd =
80+
previewParam === 'placeholder' ||
81+
(siteAdsStatus &&
82+
(siteAdsStatus === SiteAdsStatus.Pending ||
83+
siteAdsStatus === SiteAdsStatus.InReview));
7584

7685
if (!realZoneId) {
7786
return;
@@ -83,6 +92,7 @@ export function Ad({
8392
ignore: ignore || preview,
8493
zoneId: realZoneId,
8594
mode,
95+
source: showPlaceholderAd ? 'placeholder' : 'live',
8696
});
8797

8898
if (cancelled) {
@@ -97,7 +107,7 @@ export function Ad({
97107
return () => {
98108
cancelled = true;
99109
};
100-
}, [visible, zoneId, ignore, placement, mode]);
110+
}, [visible, zoneId, ignore, placement, mode, siteAdsStatus]);
101111

102112
const viaUrl = new URL('https://www.gitbook.com');
103113
viaUrl.searchParams.set('utm_source', 'content');
Loading

packages/gitbook/src/components/Ads/renderAd.tsx

+57-11
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { headers } from 'next/headers';
55
import { AdClassicRendering } from './AdClassicRendering';
66
import { AdCoverRendering } from './AdCoverRendering';
77
import { AdPixels } from './AdPixels';
8+
import adRainbow from './assets/ad-rainbow.svg';
89
import { AdItem, AdsResponse } from './types';
910

1011
interface FetchAdOptions {
@@ -16,6 +17,12 @@ interface FetchAdOptions {
1617
placement: string;
1718
/** If true, we'll not track it as an impression */
1819
ignore: boolean;
20+
/**
21+
* Source of the ad (live: from the platform, placeholder: static placeholder)
22+
*
23+
* Defaults to live.
24+
* */
25+
source?: 'live' | 'placeholder';
1926
}
2027

2128
/**
@@ -24,8 +31,9 @@ interface FetchAdOptions {
2431
* and properly access user-agent and IP.
2532
*/
2633
export async function renderAd(options: FetchAdOptions) {
27-
const { mode } = options;
28-
const result = await fetchAd(options);
34+
const { mode, source = 'live' } = options;
35+
36+
const result = source === 'live' ? await fetchAd(options) : getPlaceholderAd();
2937
if (!result || !result.ad.description || !result.ad.statlink) {
3038
return null;
3139
}
@@ -49,15 +57,7 @@ async function fetchAd({
4957
placement,
5058
ignore,
5159
}: FetchAdOptions): Promise<{ ad: AdItem; ip: string } | null> {
52-
const headersSet = headers();
53-
const ip =
54-
headersSet.get('x-gitbook-ipv4') ??
55-
headersSet.get('x-gitbook-ip') ??
56-
headersSet.get('cf-pseudo-ipv4') ??
57-
headersSet.get('cf-connecting-ip') ??
58-
headersSet.get('x-forwarded-for') ??
59-
'';
60-
const userAgent = headersSet.get('user-agent') ?? '';
60+
const { ip, userAgent } = getUserAgentAndIp();
6161

6262
const url = new URL(`https://srv.buysellads.com/ads/${zoneId}.json`);
6363
url.searchParams.set('segment', `placement:${placement}`);
@@ -78,3 +78,49 @@ async function fetchAd({
7878

7979
return null;
8080
}
81+
82+
function getPlaceholderAd(): { ad: AdItem; ip: string } {
83+
const { ip } = getUserAgentAndIp();
84+
85+
return {
86+
ad: {
87+
active: '1',
88+
ad_via_link: '',
89+
bannerid: '',
90+
creativeid: '',
91+
description:
92+
'Your docs could be this good.\nPublish incredible open source docs for free with GitBook',
93+
evenodd: '0',
94+
external_id: '',
95+
height: '0',
96+
i: '0',
97+
identifier: '',
98+
longimp: '',
99+
longlink: '',
100+
num_slots: '1',
101+
rendering: 'carbon',
102+
smallImage: adRainbow.src,
103+
statimp: '',
104+
statlink: 'https://www.gitbook.com/solutions/open-source',
105+
timestamp: Date.now().toString(),
106+
width: '0',
107+
zoneid: '',
108+
zonekey: '',
109+
},
110+
ip,
111+
};
112+
}
113+
114+
function getUserAgentAndIp() {
115+
const headersSet = headers();
116+
const ip =
117+
headersSet.get('x-gitbook-ipv4') ??
118+
headersSet.get('x-gitbook-ip') ??
119+
headersSet.get('cf-pseudo-ipv4') ??
120+
headersSet.get('cf-connecting-ip') ??
121+
headersSet.get('x-forwarded-for') ??
122+
'';
123+
const userAgent = headersSet.get('user-agent') ?? '';
124+
125+
return { ip, userAgent };
126+
}

packages/gitbook/src/components/PageAside/PageAside.tsx

+1
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,7 @@ export async function PageAside(props: {
190190
}
191191
placement="page.aside"
192192
spaceId={space.id}
193+
siteAdsStatus={site?.ads && site.ads.status ? site.ads.status : undefined}
193194
ignore={process.env.NODE_ENV !== 'production'}
194195
style={tcls('mt-4')}
195196
/>

0 commit comments

Comments
 (0)