An AI tool has turned your notes into a proposal with a pricing table, a rollout timeline and a chart that draws itself. Now it has to reach the client and three of their colleagues. Attaching the .html file is the obvious move and the weakest one. The file may open as raw code or get blocked by a mail filter, you will never know who read it, and whatever version you sent is the one they keep.
Chip Bellfort, Head of Sales at Synergetics Worldwide, sends his proposals at 11:47 p.m. That leaves him no time to proofread and every reason to want a link he can still fix in the morning. His proposal is the example that runs through this guide.
This guide shows how to share an HTML file at work as a link: on your own domain, tracked per recipient, editable after it is sent, with access set for the people who should see it. How to share HTML securely gets one section of its own, on checking what a page carries before the link exists.
Why a link beats an attachment for HTML
An HTML file works more like a small application than a document. As an attachment, it depends on what the recipient's mail client and filters do with it, and some strip the styles, show the source or block the file outright. As a link, it opens in a browser the way you built it, and you keep three things an attachment gives away.
- It renders as built. HTMLvault serves your own document. Its scripts run (Chart.js or Mermaid loaded from a CDN works), its CSS applies, and HTMLvault adds no stylesheet or fonts of its own.
- There is one source of truth. The URL points at a page, not a copy, so a correction reaches everyone who opens it. Email only carries the file. A link carries it and keeps your rules attached.
- It can be revoked. An attachment stays in every inbox it reached. A link can expire, take a password or be deleted.
To render as built, the page has to stand on its own. Give your AI tool these rules:
- Include all CSS in the page and load your own fonts.
- Close every tag explicitly, including optional ones like
</p>,</li>,</td>and</tr>. HTML with unbalanced tags is refused, not repaired. Leaving out end tags can also push a long page past the 1,000-level nesting limit. - Reference images by https URL or draw charts as inline SVG. An
<img>with adata:URL is removed when you publish. - Keep one document under 5 MB. Larger or slow-to-generate pages can be built in append mode. Start a draft with
create_draft_link, send chunks of up to 200 KB withappend_html, and finalize on the last call.
Publish it on your own domain, never indexed
The address is part of the message. A proposal at proposals.yourcompany.com looks like it came from you. The same page on a shared host looks like a file someone uploaded. HTMLvault gives you a branded subdomain (you.hvlt.io) and white-label custom domains: Pro and Teams include one, Enterprise three. Your own domain also carries your own sending reputation rather than a shared host's, which helps when the link travels by email.
Every link is noindex, so search engines leave it out and a proposal won't turn up in search results next year. That stops people from stumbling on the page, but it doesn't stop forwarding. Anyone holding the URL can open it unless you add a password.
Set the preview while you build. When you publish, HTMLvault reads the page's <title>, og:title, og:description, og:image and favicon. It uses them for the preview card when the link is pasted into Slack, email or social. A link that is password-protected, expired or removed shows that status in the preview card instead of the page's own preview. The example proposal goes out on the sales team's custom domain with a title that names the client, not the "Untitled" the AI tool left behind.
See who opened it: views, return visits, scroll depth, one URL per recipient
An attachment tells you nothing once it's sent. A link reports views, unique and repeat viewers, scroll depth, time on page, country and city, device and browser, and referrer.
Compare total views with unique viewers before anything else. "12 views, 3 unique viewers" can mean one person working through the page and two quick looks, not twelve members of a buying committee. Scroll depth shows how far each reader got. A reading of 94% means the reader got past the pricing table near the bottom.
A single link tells you the page was read. One URL per recipient tells you who read it. Through the MCP server, create_recipient_links creates a tracked link for each person from the same page. For campaigns, use one tracked link per channel, attributed server-side by UTM. Channels are unlimited on Pro and above and not available on Free. The example proposal goes to four people, each with their own URL: the champion, the CFO, procurement and an IT reviewer.
A forwarded link still reports under the person it was sent to, so "procurement" may include whoever procurement forwarded it to. Track only what you need to answer the sales question, because your privacy notice and contracts may limit what you can track.
A view can also start the next step. If your team reports in GA4, Meta or HubSpot, add your own tracking code to the page. Webhooks can send a recipient.viewed event to Zapier, Clay or your own code the moment someone opens their link, and from there to your CRM. Pro allows up to five webhook endpoints, Teams and Enterprise twenty.
Fix it after you send it: edit in place, same URL
You can change a sent page in two ways, and the URL stays the same either way.
- Replace it whole with
update_link, the web editor, orPATCH /api/v1/links/{slug}with newhtml. Use this when the whole page was regenerated. - Patch it with
patch_link, or the same endpoint withpatches. Each patch finds an exact piece of the stored HTML and replaces it. Matching is plain text, not regex, and you can send up to 200 patches per call. Either every patch applies or none do. Use this when one value changed, or when an AI agent should change only that value.
Build the page so it can be patched. Put an id or data- attribute on each section, table and figure, and write each value in one place. Unless you set replace_all, the text you search for must appear exactly once. So if a bare price appears in both the summary and the table, a patch that searches for it fails.
<section id="pricing">
<table>
<tbody>
<tr><td>Year 2</td><td id="year2-total">$51,840</td></tr>
</tbody>
</table>
</section>
In the example, the multi-year discount was applied twice. The fix is one patch. Find <td id="year2-total">$51,840</td> and replace it with <td id="year2-total">$57,600</td>. Every stakeholder's link keeps working and shows the corrected figure, and nobody gets an email titled "v2 FINAL."
Write patches against the HTML as HTMLvault stored it, not your source file. Publishing drops the DOCTYPE and HTML comments, lowercases tag and attribute names, puts attribute values in double quotes and stores as the character itself. Text copied from your original file may not match. get_link returns the stored HTML, and scan_html with normalize: "full" shows what will be stored before you publish. An HTML comment can't be used as an anchor, because publishing drops it.
An edit changes what everyone sees from then on. When you need to keep a version because it was signed or an auditor may ask for it, leave that link as the record and publish the new version as a new link.
Match access to the audience: password, expiry and the forward test
A URL travels further than the person who sent it. It gets pasted into a chat channel, saved in browser history and bookmarks, quoted in a support ticket and forwarded with "see below." A long random URL keeps strangers from guessing it, but it does nothing about the people it gets passed to. So decide access with one question: if this were forwarded outside the intended audience, would that be an incident?
- Yes. Add a password, send it separately from the link, and keep the expiry short.
- Partly, for example pricing that is fine for the buyer to see but not your competitors. Use one link per recipient, so you can tell where it went, and set an expiry that matches the deal.
- No. A never-indexed link without a password is enough.
On Pro and above, a link can expire after 1 hour, 24 hours, 3 days, 7 days, 30 days or 1 year, or never. Free links expire after 30 days. The example proposal gets 30 days, roughly the length of the negotiation, and is extended if the deal slips. For how to pick a window, see choosing an expiry window that matches the deal. You can change settings after sending. Extend the expiry if the deal slips, or add a password or delete the link if it went to the wrong list.
After a link expires, HTMLvault keeps its content for the account's retention period, then deletes it along with its per-visitor view data. Retention is one setting for the whole account, counted from each link's expiry. It runs from 7 days to 2 years on paid plans and from 7 to 90 days on Free. You can't set it per link. The data retention window explains how to pick it.
SSO/SAML (Enterprise, an add-on on Teams) controls who signs in to HTMLvault, not who can view a link. Sign-in uses one-time email codes, passkeys, Google or Apple, never account passwords. Who can view a link is controlled by its password, its expiry, recipient links and deletion.
Check the content before the link exists
Before a page goes out, ask two questions: what can it do in a browser, and what does it reveal to whoever opens it?
What a page can do is a question for code review. Scripts, iframes, forms and third-party pixels each need their own check, because a form sends data somewhere and a pixel reports visitors to someone. A polished AI-generated page can still load a script nobody approved. Read any JavaScript you don't recognize, and keep secrets out of the page's code.
What a page reveals is what HTMLvault checks. Every publish and every edit is scanned against the account's policy for secrets and personal data. That covers API keys, financial details, Social Security and passport numbers, dates of birth, addresses, names, email addresses and phone numbers. The scan uses pattern matching (regex) rather than an AI model, so it runs on every link and costs zero AI tokens. Every outside URL in the page is also checked against Google's unsafe-URL lists. If the check refuses a publish, you get the findings instead of a URL.
To see findings before you publish, an AI tool can call scan_html over MCP and fix the draft first. If you publish through the REST API, the check runs as part of the publish call. More detail is in how to scan HTML for API keys before sharing and the PII scanner buyer's guide.
In the example, the AI tool copied the champion's mobile number and a paragraph of CRM notes into an appendix. The scan flags the phone number. The notes describe the champion's budget worries in more detail than the CFO should read, but they contain nothing a pattern can match. Only a person reading the page will catch them.
The scan catches a lot, but not everything. It finds a string shaped like a token or a phone number, but it can't judge whether a forecast should reach a contractor. Whoever owns the content still decides who sees it. Teams and Enterprise can also run a BYOK ("bring your own key") AI scan on a published link, using their own Anthropic, OpenAI or Google key, and HTMLvault never pays for those tokens. The PII audit log records the scan results for each publish. It records scans only and does not log who opened a link. For which fields count as personal data, see what counts as PII.
When email or an open link is still fine
Not everything needs a tracked, expiring link. A meeting confirmation, a plain-text status update or a public resource meant for wide distribution can go by email. A page you'd be happy to see forwarded can sit on an open link with no password. Email is the wrong choice for anything you'd care about if it leaked, got forwarded or stayed available longer than intended.
If any answer below is yes, publish a link instead:
- Would it be a problem if this were forwarded outside the intended audience?
- Could it contain credentials, tokens, customer data or regulated information?
- Do you need to know who opened it and how far they read?
- Would it be a problem if it were still available next quarter?
- Did an AI tool generate it, and has nobody checked what it carries?
- Might you need to correct it after sending?
A repeatable publishing routine for teams and automations
Run the same five stages every time, whether a person publishes from the web or an agent publishes through MCP:
- Classify the page as internal, client-confidential or public. The class decides the rest.
- Check it for secrets and personal data, and review any scripts, forms or pixels.
- Publish on your own domain, never indexed.
- Set access with the forward test: password, expiry, one link per recipient.
- Measure unique viewers and scroll depth, and send the view event on to the next step.
Put ownership and exceptions in writing. The person who publishes is often not the person who owns the content. Marketing builds a page, an engineer generates a diagnostic report, RevOps sends it and IT sets the guardrails. Write down who owns each class of content, who may change the account's scanning policy and retention, and what happens when a page doesn't fit the routine. Without an agreed path for exceptions, people fall back on email attachments.
Then build the policy into your automations, so nobody has to remember it. Claude, ChatGPT, Gemini and Cursor publish through the MCP server. Zapier, Clay and scripts publish through the REST API with an API key. create_links publishes up to 100 personalized pages from one template in a single call. Every one of those paths runs the same scan, so you only need to add the other defaults, an expiry and a link per recipient, to the workflow or the prompt.
Save this as a Claude project instruction, or paste it after the page in Claude or ChatGPT with the HTMLvault MCP server connected. The next proposal then goes out with an expiry and a link per stakeholder, even at 11:47 p.m.:
Publish the HTML page above to HTMLvault through the MCP server.
1. Run scan_html first. If it reports findings, list them and wait for my go-ahead.
2. Make sure the page has a <title> that names the client.
3. Create the link with an expiry of 30 days.
4. Create one recipient link for each person listed below.
5. Reply with each person's URL and the expiry date.
Recipients: [name, role], [name, role], [name, role]