@@ -5,6 +5,7 @@ import { headers } from 'next/headers';
55import { AdClassicRendering } from './AdClassicRendering' ;
66import { AdCoverRendering } from './AdCoverRendering' ;
77import { AdPixels } from './AdPixels' ;
8+ import adRainbow from './assets/ad-rainbow.svg' ;
89import { AdItem , AdsResponse } from './types' ;
910
1011interface 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 */
2633export 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+ }
0 commit comments