Link access
You have a report, a benchmark, a workshop handout — something people want, that you are willing to give away, but not anonymously. Upload it, switch the link to capture emails, and every visitor is asked for an address before the page loads. They confirm a six-digit code, the page appears, and the address is yours.
This is the thing usually called an email gate or a lead magnet, and normally it means wiring a form to a mailing-list provider, then hiding the real page behind whatever that provider redirects to. Here it is a property of the link. Nothing is embedded in your HTML, nothing is added to the page, and the document you uploaded is the document that gets served once someone is through.
The gate is enforced by the API, not by a script on the page. A visitor who has not given an address receives the form and nothing else — the document is still on the server. That matters because the alternative most people reach for is a form overlaid on content that has already been delivered, where the whole page sits in view-source underneath the thing asking for an email, and anyone who presses Escape reads it anyway.
The wall lives on the site's own URL rather than a redirect, so the link you sent is the link that works, and someone who bookmarks it lands back in the right place.
You choose these when you turn the mode on, and can change them afterwards without the URL moving.
Code required, or address only
With the code on, an address is only marked verified once someone has proved they can read mail sent to it. With it off, a visitor types an address and goes straight in, and the list will contain whatever people typed.
30 days · 7 days · every visit
How long someone stays let in before being asked again. “Every visit” is stored as a session cookie rather than a zero-length pass, so it lasts as long as their browser is open and no longer.
One, several, or any
Only addresses at these domains get in, and anyone else is told so plainly instead of waiting for a code that will not come. Separate several with commas. Subdomains are covered by their parent, so sales.acme.com is admitted by acme.com.
The one that decides everything is the first. A list of addresses nobody confirmed is a list of what people were willing to type, and a good proportion of any such list is somebody@example.com. Requiring the code costs you the visitors who will not wait fifteen seconds for a message, and buys you a list where every entry is a real inbox belonging to the person who used it. Which of those you want is a genuine decision, and it is worth making deliberately rather than leaving on the default.
Every site in this mode grows a Visitors tab: the addresses, whether each was verified or only ever sent a code, and the date it first appeared. It is searchable, filterable by status, and exports as CSV. The count that usually surprises people is code sent, never used — those are the ones who wanted it enough to type an address and then did not finish, which is a different and more useful signal than a missing row.
What you do not get is analytics. Nothing here counts page views, measures how long anyone stayed, or tells you when a particular person came back — none of that is collected anywhere in pagegoat, on any plan. If what you actually want is read receipts on a document, this is the wrong product and it is better to hear that now.
Switching the site back to public, private or password stops collection and leaves the list alone. It stays on the Visitors tab until you delete the rows, the site, or your account. The addresses belong to your visitors rather than to us, which also means the obligation to have told them what you were collecting it for is yours — the privacy policy sets out how that splits.
Two calls, the same shape as every other visibility change: publish, then set the mode.
# 1. Publish the page (multipart: a .html file, or a .zip with index.html)
curl -X POST https://api.pagegoat.com/api/sites \
-H "Authorization: Bearer $TOKEN" \
-F "title=2026 benchmark report" \
-F "slug=benchmark-2026" \
-F "file=@./report.html"
# 2. Ask every visitor for an email first.
# captureOtp true = a 6-digit code must be confirmed; false = address only
# captureReverifyDays 30 | 7 | 0 (0 means every visit)
# captureDomains "acme.com, northloop.co" — or "" for any domain
curl -X PUT https://api.pagegoat.com/api/sites/benchmark-2026/visibility \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"visibility":"capture","captureOtp":true,
"captureReverifyDays":30,"captureDomains":""}'One honest limit. An AI agent connected over MCP cannot switch this mode on: its set_visibility tool accepts private, password and public only. Ask Claude or ChatGPT to publish the page and it will; ask it to put an email gate on the page and it will keep failing, whatever you call it. Set the mode yourself afterwards, in the Sharing tab or with the call above.
Asking for an email is the right gate when you are happy for the page to reach anyone who asks and the point is knowing who asked. It is the wrong one when the content is genuinely confidential, because an address is a claim rather than an identity, and a code proves only that someone can read that inbox.
All four are the same setting on the same URL, so a page can start gated and open later without the link you already sent going stale. The rest of them are indexed on solutions, and sharing a report with a client walks through choosing between them for one specific job.
Upload the page, then set its link access to capture emails. From then on a visitor who opens the URL gets a short form instead of the page: they enter an address, we mail them a six-digit code, and the page loads once they type it back. Nothing of the document is sent until that happens, because the gate is enforced by the API rather than by a script on the page. You set three things when you turn it on — whether the code is required, how long someone stays let in before they have to do it again, and which email domains you will accept. Everything captured shows up on the site's Visitors tab.
No, and the choice is the whole difference between two quite different lists. With the code required, an address is only recorded as verified once someone has proved they can read mail sent to it, so what you keep is a list of addresses that actually exist and belong to the person who used them. With it switched off, a visitor types an address and goes straight in with nothing checked, so the list will contain whatever people typed — which is a real trade, not a lesser setting. Take the code when the list is the point. Skip it when getting people to the page matters more and you would rather ask politely than block anyone.
Yes. The allowed-domains box takes one domain or several separated by commas, and only addresses at those domains get in; anyone else is told so plainly rather than being left to guess why the code never arrived. Subdomains are covered by their parent, so sales.acme.com is admitted by acme.com, and writing it as @acme.com works too. Leave the box empty and any address is accepted, which is what you want for something published to the world. The restriction is shown to the visitor before they type, so a refusal is predictable instead of arriving after they have already committed an address.
A list, on the site's Visitors tab: every address, whether it was verified or only sent a code and never used, and the date it first appeared. You can search it, filter it by status, delete individual rows, and export the whole thing as CSV whenever you like. What you do not get is analytics — nothing counts page views, records how long anyone stayed, or tells you when a particular person came back, because none of that is collected anywhere in pagegoat. If you are looking for read receipts on a document, this is the wrong product and the honest answer is to say so.
It stays. Turning the mode off stops collection and lets the people already through keep their pass, but nothing in the list is touched — a mode you switched on and off still holds everything it gathered, waiting on the Visitors tab. Three things remove those rows: deleting them yourself, deleting the site, or deleting your account. This is deliberate, because the alternative is that flipping a setting silently destroys the list, and someone would only discover it by coming back to an empty table. The addresses belong to your visitors, so you are responsible for having told them what you collected it for.
A script can; an AI agent cannot, yet. Over the REST API you set it the same way as any other mode, with a PUT to the visibility endpoint naming capture along with captureOtp, captureReverifyDays and captureDomains, so a deployment pipeline can publish a gated page on every merge. The MCP connector is the gap: its set_visibility tool accepts private, password and public only, so asking Claude or ChatGPT to put an email gate on a page will fail whatever you call it. An agent can create the page and you set the mode afterwards in the Sharing tab, which is two steps rather than one.
Included on every paid plan, from $2.99 a month. No form to embed, no mailing-list account, and no separate tool between your page and the people who want it.
pagegoat.com/sites/your-report
See plans