我正在尝试在我的 React 应用程序新闻源上返回测试广告,但 NPM 似乎缺乏文档。我唯一能找到的东西是来自 eBayClassifiedsGroup/react-advertising。这是我的第 1 步代码(参见第 46-54 行):
import React, { Component } from 'react';
import './App.css';
import News from './News/News';
import SideFeed from './News/SideFeed';
import {
AdvertisingProvider,
AdvertisingSlot,
} from 'react-advertising';
import config from './News/config'
class App extends Component {
constructor(props) {
super(props);
this.state = {
news1: {
type: 'top-headlines',
query: 'sources=bbc-news'
},
news2: {
type: 'everything',
query: 'domains=techcrunch.com&language=en'
},
news3: {
type: 'everything',
query: 'domains=comicbookmovie.com&language=en'
}
};
}
render() {
return (
<div className="container-fluid">
<div className="navbar-fixed">
<nav>
<div className="nav-wrapper indigo lighten-4">
<a href="/" className="brand-logo center">RF News Feed as of 6 DEC 2021</a>
</div>
</nav>
</div>
<div className="row">
<div className="col s8">
<News news={this.state.news1} />
<News news={this.state.news2} />
<div id="banner-ad"
style= { {
width: 300,
height: 250
}}>
<AdvertisingProvider config={config} />
<AdvertisingSlot config={config} />
</div>
</div>
<div className="col s4">
<SideFeed news={this.state.news3}/>
</div>
</div>
</div>
);
}
}
export default App;
第 2 步:唯一的广告依赖项位于下面的 config.js 中:
import React from 'react';
const config = {
slots: [
{
id: "banner-ad",
path: "/6355419/Travel/Europe/France/Paris",
sizes: [[300, 250]]
}
]
};
export default config;
任何人都可以看一下或向我推荐有关React的GPT广告实施的资源吗?
我看到您尝试获取 npm 软件包,但不需要。在这里,我将用更新的代码解释如何像普通网页实现一样进行操作。
您好,我知道文档 GPT(Google 发布商标签)不太好并且缺少一些信息...
所以在这里我将描述如何在我的 ReactJS(使用 Typescript)应用程序中实现 GPT 广告。
首先,我通过添加 window.googletag 属性并配置它来初始化广告。
inits/gptAds.ts
export const initialiseGPTAds = () => {
if (typeof window !== 'undefined') {
// Ensure we can interact with the GPT command array.
window.googletag = window.googletag || { cmd: [] };
// Prepare GPT to display ads.
googletag.cmd.push(() => {
// Disable initial load, to precisely control when ads are requested.
googletag.pubads().disableInitialLoad();
// Enable SRA and services.
googletag.pubads().enableSingleRequest();
googletag.enableServices();
});
// Here I save my slots into my zustand or redux state so I can access them later and have better control.
const { setAdSlots } = useAppStore.getState();
setAdSlots({ count: 0, slots: {} });
}
};
我将常量分开,这样我就可以在有限或不受限的广告库之间交换。
consts/gptAds.ts
export const gptAdsUrl = 'https://securepubads.g.doubleclick.net/tag/js/gpt.js';
export const gptLimitedAdsUrl = 'https://pagead2.googlesyndication.com/tag/js/gpt.js';
我创建了一个钩子,因此我在应用程序初始化(app.tsx)时调用它。该钩子将注入脚本库(受限或不受限),并将在加载时初始化广告。
挂钩/初始化GPT.tsx
import * as React from 'react';
import { gptAdsUrl, gptLimitedAdsUrl } from 'app/consts';
import { initialiseGPTAds } from 'app/inits';
const useInitializeGPT = (limitedAds: boolean = false) => {
React.useEffect(() => {
const scriptUrl = limitedAds ? gptLimitedAdsUrl : gptAdsUrl;
const script = document.createElement('script');
script.src = scriptUrl;
script.async = true;
document.head.appendChild(script);
script.onload = () => initialiseGPTAds();
// Cleanup function to remove the script when the component unmounts
return () => {
document.head.removeChild(script);
};
}, [limitedAds]);
};
export default useInitializeGPT;
然后我在我的 main.tsx 或 app.tsx 上这样调用:
useInitializeGPT(false);
我创建了一些服务,以便我可以定义广告位、销毁定义的广告位、请求广告并获取最小广告位大小(用于横幅)。
这里我定义了广告位并保存到我的状态中以便更好地控制。每个广告位都需要尺寸(用于横幅)和 AdUnit。 您可以使用测试 AdUnit 例如“/6355419/Travel/Europe”来测试。
服务/gptAds/defineAdSlot.ts
import { useAppStore } from 'shared/store';
import { reportError } from 'shared/utils';
export const defineAdSlot = (adUnit: string, size: googletag.GeneralSize) => {
const { adSlots, addAdSlot } = useAppStore.getState();
try {
const newSlotId = `slot-${adSlots.count}`;
let newSlot: googletag.Slot | undefined;
googletag.cmd.push(() => {
const slot = googletag.defineSlot(adUnit, size, newSlotId);
if (!slot) throw new Error('defineAdSlot: Not possible to add ad slot.');
slot.addService(googletag.pubads());
googletag.display(slot);
addAdSlot(slot, newSlotId);
newSlot = slot;
});
return { newSlot, newSlotId };
} catch (error) {
reportError(error, 'defineAdSlot');
return { newSlot: undefined, newSlotId: undefined };
}
};
在这里,我销毁了该插槽,以防来回导航并避免口是心非。
服务/gptAds/destroyAdSlot.ts
import { useAppStore } from 'shared/store';
import { reportError } from 'shared/utils';
export const destroyAdSlot = (slotId: string) => {
const { removeAdSlot, adSlots } = useAppStore.getState();
try {
googletag.cmd.push(() => {
if (adSlots.slots[slotId]) {
googletag.destroySlots([adSlots.slots[slotId]]);
removeAdSlot(slotId);
}
});
} catch (error) {
reportError(error, 'destroyAdSlot');
}
};
这里的这个函数主要是一个推荐(来自官方 GPTAds 示例),所以我在渲染广告时在布局中使用(请检查下面)。
服务/gptAds/getMinimumSlotSize.ts
export const getMinimumSlotSize = (size: googletag.GeneralSize) => {
const maxValue = Number.MAX_VALUE;
let minW = Number.MAX_VALUE;
let minH = Number.MAX_VALUE;
if (Array.isArray(size)) {
// Convert googletag.SingleSize to googletag.MultiSize for convenience.
const sizes = size.length <= 2 && !Array.isArray(size[0]) ? [size] : size;
for (const s of sizes) {
if (Array.isArray(s) && s[0] !== 'fluid') {
minW = Math.min(+s[0], minW);
minH = Math.min(+s[1], minH);
}
}
}
return minW < maxValue && minH < maxValue
? // Static ad slot.
{ minWidth: `${minW}px`, minHeight: `${minH}px` }
: // Fluid ad slot.
{ minWidth: '50%' };
};
在这里,我请求将广告位作为参数提供的广告。
服务/gptAds/requestAds.ts
import { reportError } from 'shared/utils';
export const requestAds = (adSlots: Record<string, googletag.Slot>) => {
try {
googletag.cmd.push(() => {
const slots = Object.values(adSlots);
googletag.pubads().refresh(slots);
});
return true;
} catch (error) {
reportError(error, 'requestAds');
return false;
}
};
这是我在组件中渲染的方式,以便它可以在任何地方显示。我使用 React.memo 来避免重新渲染广告位并导致问题。
组件/adSlotContainer.tsx
const AdSlotContainerComponent = ({ adUnit, size }: Props) => {
const hasLoaded = React.useRef<boolean>(false);
const [slotId, setSlotId] = React.useState<string>();
React.useEffect(() => {
if (hasLoaded.current) return;
const { newSlot, newSlotId } = defineAdSlot(adUnit, size);
if (!newSlot || !newSlotId) return () => {};
const requested = requestAds({ [newSlotId]: newSlot });
if (!requested) return () => {};
hasLoaded.current = true;
setSlotId(newSlotId);
return () => {
slotId && destroyAdSlot(slotId);
};
}, [adUnit, size]);
return slotId ? (
<div
className={classes(styles.adSlot, styles.centered)}
style={getMinimumSlotSize(size)}
id={slotId}
key={slotId}
></div>
) : null;
};
const propsAreEqual = (prev: Props, next: Props) => {
return prev.adUnit === next.adUnit && prev.size === next.size;
};
export const AdSlotContainer = React.memo(AdSlotContainerComponent, propsAreEqual);
最后,这是我如何在任何组件中渲染它:
页面/测试/组件/horizontalContainer.tsx
import { AdSlotContainer } from 'app/components';
import styles from './styles.module.scss';
export const HorizontalContainer = () => {
return (
<div className={styles.container}>
<div className={styles.bannerAd}>
<AdSlotContainer adUnit="/6355419/Travel/Europe" size={sizes.bottomDesktop} />
</div>
</div>
);
};
这里是要使用的横幅尺寸示例:
// Here are just examples of sizes
const sizes: Record<string, googletag.GeneralSize> = {
bottomMobileBanner: [468, 60], // Full Banner
bottomDesktopBanner: [728, 90], // Leaderboard
rightDesktopRect: [300, 250], // Medium Rectangle
rightDesktopTall: [160, 600], // Wide skyscraper
};
注意事项: 在我的项目中,我已经组织好了所有文件夹,所以我建议相同,并且还使用索引(导出*)文件来使绝对导入更好。我到处都有“reportError”功能,它会发送到我的 Crashlytics 或 Sentry 并记录它。
我还添加了库“@types/google-publisher-tag”作为开发依赖项,并将其包含在 tsconfig.json 中的类型中:
"types": [(...), "google-publisher-tag"]
,以便类型正常工作。