Docs
Install PubTrust
One tag, loaded async, in Monitor mode. Nothing is blocked until you turn blocking on. Ten minutes for a standard GPT or Prebid stack.
Where does the PubTrust tag go?
As high in the <head> as you can put it, above your ad stack, loaded async. Being early matters because the first detection layer hooks your ad library's events, and hooks installed after the first bid has already resolved will miss it. Being async matters because nothing we do should sit on your critical rendering path. If the tag is not there when your ad stack initialises, PubTrust falls back to the DOM and runtime layers and reports the degraded coverage in your dashboard rather than pretending everything is fine.
<script async src="https://cdn.pubtrust.cc/t/YOUR_TAG_KEY.js"></script>That is the whole installation. Your tag key is on your Site's Install page. The file is per-site: it carries your resolved configuration — mode, slot selectors, fallback creatives, sampling rate, enabled policies — plus the critical inline rule set, so protection is live before anything else loads.
Can I install PubTrust through Google Tag Manager?
Yes, with one trade-off to understand first. A Custom HTML tag runs when your GTM container fires, which is later than a script placed directly in the <head>. PubTrust attaches its Prebid and GPT hooks through pbjs.que and googletag.cmd, so the hooks install correctly whichever script loads first — but a bid or render event that fired before PubTrust loaded is not replayed to it. Ads that arrive after the tag loads get every layer; ads that won before it loaded miss pre-render scanning. For the earliest coverage, put the script tag in the page itself.
<script>
(function () {
var s = document.createElement('script');
s.async = true;
s.src = 'https://cdn.pubtrust.cc/t/YOUR_TAG_KEY.js';
document.head.appendChild(s);
})();
</script>Configure the tag
- Paste the snippet above into a Custom HTML tag, replacing
YOUR_TAG_KEYwith the key from your Site's Install page. - Fire it on the Initialization – All Pages trigger, which runs before Page View triggers.
- If your ad stack is also deployed through GTM, give the PubTrust tag a higher tag firing priority than the ad-stack tags.
- If you use
window.__ptDisable, set it before this tag fires; it is read once, when the tag starts. - Publish the container, then check that it is working.
GTM Custom HTML tags usually need your Content Security Policy to allow GTM's own script injection. That requirement comes from GTM; the PubTrust tag itself still needs only the two hosts listed below.
Do I have to tell PubTrust where my ad slots are?
Usually not. PubTrust auto-discovers the standard containers — [id^="div-gpt-ad"], ins.adsbygoogle, iframe[id^="google_ads_iframe"] — and you can mark anything else with data-pt-slot. If your stack uses custom containers, add selectors on the Site's settings page rather than in code, so you can change them without a deploy.
<div id="sidebar-mpu" data-pt-slot="sidebar-mpu-300x250"></div>How do I get pre-render blocking with Prebid?
Install the Real-Time Data module. The standalone tag already hooks pbjs.onEvent for bidResponse and bidWon and reads bid.adm, which gives you creative-markup scanning before render. The RTD module goes further: it judges every bid’s creative markup before the bid enters the auction and rejects a bid whose creative violates a policy in Block, so that creative never competes, never wins and never executes, rather than being hidden after it has rendered. For malvertising specifically, that is the difference that matters — a hidden iframe still runs its payload.
// Build Prebid with the module: gulp build --modules=rtdModule,pubtrustRtdProvider
pbjs.setConfig({
realTimeData: {
dataProviders: [{
name: 'pubtrust',
params: { tagKey: 'YOUR_TAG_KEY' }
}]
}
});No auctionDelay is needed: the module does not enrich bid requests, so PubTrust never delays your auction. Only in the first auction on a page, if the tag has not loaded yet, is a bid held — for at most waitForTagMs, 500 ms by default and never more than 5,000 ms — after which it proceeds unjudged and the fail-open is counted and shown to you. Set monitorOnly: true to report without rejecting anything.
What about Google Publisher Tag?
Nothing to configure. PubTrust hooks slotRequested, slotResponseReceived and slotRenderEnded automatically, and calls getResponseInformation() for advertiser, campaign and creative identifiers. It also captures responseIdentifier from slotRenderEnded on every violation, which is the value Ad Manager's Ad Review Center accepts to block that exact ad — so each catch gives you a permanent upstream block in your own ad server, on the violation row.
My ad stack is custom. Can I still use this?
Yes — push slot and creative information onto window.__ptSlots and PubTrust treats it exactly like a Prebid or GPT signal, including the pre-render layer.
window.__ptSlots = window.__ptSlots || [];
window.__ptSlots.push({
slotId: 'sidebar-mpu-300x250',
el: document.getElementById('sidebar-mpu'),
adomain: ['advertiser.example'],
creativeId: 'abc-123',
cpm: 2.40, currency: 'EUR',
adm: '<html>…</html>' // optional; enables pre-render markup scanning
});Having PubTrust render the creative
Add render: true with the markup in adm and PubTrust renders the creative itself, through inert-park: the markup is held as inert text, judged, and then written into the slot — or, on a Site in Block, discarded in favour of your fallback — so a violating creative never executes. A parked creative waits up to 750 ms for the full rule bundle, renders unjudged after 5,000 ms, and every fail-open is reported. The slot element comes from el, or from slotId as an element id. See inert-park.
window.__ptSlots = window.__ptSlots || [];
window.__ptSlots.push({
slotId: 'sidebar-mpu',
el: document.getElementById('sidebar-mpu'),
adm: '<html>…</html>',
size: '300x250',
adomain: ['advertiser.example'],
creativeId: 'abc-123',
render: true, // PubTrust renders after judging
onRender: function () {},
onBlock: function (verdict) {},
onDecision: function (outcome) {} // { action, reason }
});What do I need to add to my Content Security Policy?
Two hosts, and nothing else. cdn.pubtrust.cc for the tag and policy bundles, and in.pubtrust.cc for beacons. PubTrust needs no unsafe-inline and no unsafe-eval.
script-src 'self' https://cdn.pubtrust.cc;
connect-src 'self' https://cdn.pubtrust.cc https://in.pubtrust.cc;If you use Subresource Integrity elsewhere, note that the per-site tag is regenerated when your configuration changes, so a pinned hash would break on every policy edit. Pin the origin, not the file.
How do I check it is working?
Open your site and run window.__pubtrust.policies() in the browser console: a running tag lists every policy it has loaded, with its mode and rule count, and window.__pubtrust.errors() shows anything it has caught. Your dashboard's Install page shows live tag status per site — last beacon, tag version, bundle hash, and whether any layer is degraded. In Monitor mode the violation feed begins filling immediately; if it is empty after real traffic, the Install page will say which layer is not reporting and why.
When should I switch from Monitor to Block?
When you have looked at a week of your own violations and you believe them. The honest sequence: run Monitor for seven to fourteen days; sort violations by estimated revenue impact descending and read the expensive ones; allowlist the advertisers you recognise as legitimate; adjust the weights that are firing on your own editorial vocabulary; then enable Block one policy at a time, starting with Malware & Scam and Runtime Integrity, which almost never produce a disagreement. Leave the editorially-entangled packs — Political, Weapons, Alcohol, Shock — in Monitor for longer than you think you need to.
How do I turn it off?
Set the Site to Off in the dashboard and running tags go inert at their next configuration poll — within about five minutes — without you deploying anything. Set window.__ptDisable = true before the tag loads and it never initialises. Or delete the script tag. We do not think a vendor should be difficult to remove, and a vendor who is difficult to remove should not be trusted with your pages.