` placements in your
pages. With view transitions, the tag starts a new page view on each navigation.
---
# Serve through Google Ad Manager
> Run TerraGaming Media units as GAM custom HTML creatives (SafeFrame off).
If your ad slots are managed in Google Ad Manager (GAM), each TerraGaming Media unit runs as a
**custom HTML creative**.
## 1. One creative per unit
In GAM, create a **Third-party** (custom HTML) creative for each placement, and **turn off “Serve
into a SafeFrame”**. The tag cannot run inside a SafeFrame and stays off there.
## 2. Creative code
Each creative carries its own loader, because a creative runs in its own frame. This is the only
case where a unit includes `tag.js`:
```html
```
Before your CNAME is verified, the loader carries your ids:
``.
The portal's **Get Tags → Google Ad Manager** tab shows each unit's creative code.
## Notes
- The page itself needs no site tag for GAM-only placements. In-article ads need the site tag on the
page.
- Consent: the creative reads your consent manager from the page (friendly iframe), the same as on
the page.
---
# Single-page apps and client-side routing
> How the tag follows route changes, late placements and unmounts, and when to use manual mode.
The tag handles client-side navigation by itself (`spa: "auto"`, the default).
## What counts as a new page
- `history.pushState` or back/forward to another **path or query** starts a new page view. The tag
waits for the new route to render: once your page's DOM has changed, until it has been quiet for
250 ms. If nothing changes within a second, it assumes the route rendered before the URL changed.
It never waits more than 3 seconds.
- `history.replaceState` (infinite scroll, UTM clean-up) and hash-only changes **never** start a page
view, so ads on screen stay.
- A new page view removes the previous page's ads, finds your article again and decides every
placement on the new page. The floating banner stays unless you set `floating: "per-pageview"`.
## Placements mounted later
A `
` added after load (a component mounting, "load more") is decided
automatically in the current page view. When it is removed, its ad is removed too. Units that were
not filled are tried again on the next page view.
## Manual mode
If your router renders the new page more than about a second after the URL changes (slow loaders),
or you want exact control, set manual mode and tell the tag when the new page is ready:
```html
```
(or `spa: "manual"` in `window.tgmConfig`, or the `spa` option of the packages), then:
```js
// after each navigation has rendered:
window.tgm?.pageview();
```
Calling `tgm.pageview()` yourself also switches the tag to manual mode. A call right after the tag's
own page view for the same URL is merged into it, so you never count a page twice.
## The API
| Call | Does |
| --------------------- | ----------------------------------------------------------------------------------------------------------- |
| `tgm.pageview()` | Starts a new page view (manual mode). |
| `tgm.refresh(["id"])` | Decides the given placements again in this page view. |
| `tgm.destroy()` | Removes every ad and stops the tag. Loading `tag.js` again starts a fresh one. |
| `tgm.on(event, cb)` | `render`, `unfilled`, `viewable`, `close`, `decide`, `pageview`, `remove`. Returns an unsubscribe function. |
| `tgm.status()` | Configuration, state and every slot, for checking an install. |
---
# Content Security Policy and consent
> The CSP directives the tag needs, and how it follows your visitors' privacy choices.
## Content Security Policy
If your site sends a `Content-Security-Policy` header, allow your tag host (`tgmads.example.com`,
or `cdn.terramedia-sandbox.com` before your CNAME is verified):
```text
script-src https://tgmads.example.com;
connect-src https://tgmads.example.com;
frame-src https://tgmads.example.com;
```
The one-line site tag needs **no** `'unsafe-inline'`. With a nonce-based policy, add the nonce to the
`
```
That one line is the whole site tag once your CNAME is verified. The tag reads your property's settings from your own host, including the article selector you set in the portal. Before verification it also carries your ids as `data-tgm-*` attributes. Add it **once**: it serves every ad unit on the page, so you never add it again for a new unit.
The site tag also runs in-article placements automatically, using the in-article ad unit created with your property. Single-page apps (React, Next.js, Vue, Nuxt…) need nothing extra: the tag follows route changes by itself.
There are step-by-step guides for [HTML](../install/html/), [WordPress](../install/wordpress/), [Laravel](../install/laravel/), [React / Next.js](../install/react/), [Vue / Nuxt](../install/vue/) and [Google Ad Manager](../install/google-ad-manager/). The Install dialog also copies ready-made instructions for an [AI assistant](../install/ai-assistant/).
### 3. Place ad units
Add each ad unit's placement where the ad should appear, for example `
` (see _Creating Ad Units and Placing Tags_).
### 4. Check it
The Install dialog shows **Tag detected** within about 10 minutes of the first visit. In the browser console, `window.tgm.status()` shows your property and every placement on the page.
### Consent and privacy
The tag honours Global Privacy Control and your consent platform: when a visitor declines advertising, no TerraGaming Media cookie is set.
---
# Creating Ad Units and Placing Tags
> Create ad units for each placement and drop their placements into your pages, apps or Google Ad Manager.
An **ad unit** is one placement on your site with a fixed size. Each has an ID such as `TGM-SPN-MOB01` that you will see in your reports.
### Creating an ad unit
Open **Ad Units & Tags**, select **Create New Ad Unit**, choose the property and the slot size — **300x250**, **728x90**, or the **floating banner**, which anchors to the bottom of the screen — and name it after where it appears. Then copy its placement from **Get Tags** on the unit's row. Tags become available once the property is approved and live on our network.
### Placing an ad unit
A placement is markup only. It never includes the tag, because the **site tag** is added once per site (see _Installing the Site Tag and Your CNAME_):
```html
```
- **HTML**: paste the placement where the ad should render. The same unit can appear on many pages, and more than once on a page.
- **WordPress**: use the TerraGaming Media Ad block, widget or the `[tgm_ad unit="…"]` shortcode from our plugin, or a Custom HTML block.
- **Apps and frameworks**: the React, Vue and Laravel packages render it as `
` or `
`.
- **Google Ad Manager**: add the GAM snippet from **Get Tags → Google Ad Manager** as a custom (third-party) HTML creative with **Serve into a SafeFrame** turned off. SafeFrame delivery is not supported. This is the only placement that carries its own loader, because a creative runs in its own frame.
### Checking delivery
**Revenue Reports** breaks impressions and earnings down by ad unit.
---
# Blocking Advertisers and Ad Categories
> Control which advertisers and kinds of ads appear on your sites.
You decide which ads appear on your properties. Changes take effect across our network within minutes.
### Advertiser Blocklist
Under **Advertiser Blocklist**, search for an advertiser and block them on all your properties or only on selected ones. Blocked advertisers' campaigns are never served on those sites. You can remove a block at any time.
### Category Filters
Under **Category Filters**, switch off whole categories of ads (Sportsbook; Slots & Video Poker; Table Games & Live Dealer; Bingo & Lottery; Poker & Cardroom) for all your properties at once, or override the network-wide setting for a single property. Multi-tab interactive banners are not affected by these filters.
### Who can change them
Owners, Admins and Standard members can edit blocklists and category filters; Read Only members can't.
---
# Setting Up Payouts and Tax Information
> Get paid by bank transfer or stablecoins, and understand payout timing and your 1099.
Set up how you are paid under **Payout Settings**. Only organization Owners and Admins can see earnings and payouts.
### Payout methods
- **Direct Deposit (ACH / Wire)** — connect your bank through Stripe Connect. You are redirected to Stripe to verify your business and tax details and link your account.
- **Cryptocurrency** — USDC or USDT on Ethereum (ERC-20), or USDC on Solana. Network fees are deducted from the payout, and funds sent to a wrong address cannot be recovered, so double-check it.
U.S. publishers must complete Stripe onboarding (including tax details) before any payout, even when paid in crypto.
### When you are paid
Earnings for a month are paid on the **1st of the month after next** — once the advertisers have been charged. For example, January's earnings are paid on March 1. The minimum payout is **$100**; smaller balances roll over to the next payout. Every payout has a statement under **Payment History**.
### Tax documents
U.S. publishers receive a **1099-NEC** each year by the end of January in the **Tax Documents** center; we email you when it is ready. International publishers are exempt. TerraGaming Media does not provide tax advice.
---
# Managing Publisher Users & Roles
> Invite your team and choose what each member can see and change.
Give your team access to your publisher workspace with the right permission tier.
### Permission tiers
- **Admin** — full control: users, payout settings and tax documents. The primary administrator is always an Admin.
- **Standard** — manage properties, ad tags, category filters and blocklists. No payouts or user management.
- **Read Only** — view revenue reports, audience insights and payment history.
### Inviting a user
Open **Manage Organization**, select **Invite User**, enter their email and choose a tier. They receive a one-time invitation link, valid for seven days. You can resend or revoke pending invitations.
### Notifications
Each member chooses their own email notifications under **Notification Preferences** — website approval status, payment method changes, tax documents, payouts and network announcements. Security emails are always sent.
### Account security
Turn on two-factor authentication under **Account Security**, where you can also review and sign out of your active sessions.