Every marketing email HubSpot has ever sent on your behalf ends the same way. A HubSpot unsubscribe link and a manage-preferences link, printed on your own subdomain, pointing at a HubSpot system path, carrying a token that only HubSpot can read. The day that subdomain stops pointing at HubSpot, or the day the portal closes, every one of those links returns a 404. The emails do not know that. They are sitting in inboxes, and some of them will be opened next year.
That is a legal problem before it is a cosmetic one. The FTC’s compliance guide for the CAN-SPAM Act says an opt-out mechanism must be able to process requests “for at least 30 days after you send your message”, that a request must be honored “within 10 business days”, and that a sender may not require “any step other than sending a reply email or visiting a single page”. 1 Source 1 Federal Trade Commission, “CAN-SPAM Act: A Compliance Guide for Business,” ftc.gov. The guide states that any opt-out mechanism must be able to process requests for at least 30 days after the message is sent, that requests must be honored within 10 business days, and that a sender may not require any personally identifying information beyond an email address or any step other than sending a reply email or visiting a single page. Changing email platforms moves your sending. It does not move the obligation, because the obligation is attached to mail you have already sent.
We are working through this on an exit now. The portal belongs to a small B2B software company. Its HubSpot contract is ending, and on the day we opened the portal a three-email welcome sequence and a 13-email nurture were still sending. What follows is what the portal held, what the law required of it, and the one-field page that discharges the obligation for as long as the old emails exist.
Why do HubSpot’s unsubscribe links stop working when you leave?
HubSpot sends marketing mail from a subdomain you delegate to it, something like email.yourcompany.com, and the two links in every footer go to paths on that subdomain. HubSpot’s servers answer them. On the portal we audited, all 16 emails in the live sequences carried both links, the unsubscribe and the preferences page, and both resolved to HubSpot.
Each link identifies the recipient with a token in the query string. The token is opaque and signed by HubSpot. 2 Definition 2 Opt-out token: the recipient identifier HubSpot appends to its unsubscribe and manage-preferences links. It is opaque and HubSpot-signed, so a server outside HubSpot cannot decode it into an address. Because it identifies a person, it must be treated as personal data and never logged, stored in a URL, or sent to analytics. Nothing outside HubSpot can turn it back into an email address. The moment the subdomain is repointed at your new site, a click on an old link arrives at a server that has never seen the token and cannot say whose it is. After the portal ends, nobody can.
So two things fail together. The path stops existing, and the identity behind the click stops being knowable. The first is a routing fix. The second shapes everything about what the replacement page can do.
The people clicking are real
It is tempting to treat this as a theoretical exposure. The emails are old, the audience is small, who is going to click.
They click. On this portal, recipients unsubscribed seven times in ten days while we were planning the exit, every one of them through the link in the email, about one every two days. The welcome sequence and the nurture were both still sending. Those seven people got what they asked for because HubSpot was still answering the link. The same seven, a month later, after a subdomain move done on the wrong day, would have landed on a 404 and had one option left: the spam button.
That button is the actual cost. A complaint is logged against the sending domain, and a new domain in its first weeks of warming has no reputation to absorb it. The company would be building deliverability on a platform it had just moved to while its own old emails taught recipients to report it.
The subdomain was carrying more than the opt-out
The first thing we measured was which host HubSpot’s opt-out links used. Three readings in the portal agreed: the marketing-email subdomain was listed as the primary marketing email domain, all 435 marketing emails had it as their active domain, and every one of the 369 published web versions lived on it.
The same settings page named it as something else as well: the click-tracking domain. Click tracking was switched on for both HTML and plain text, which means every link in every email the portal had ever sent, not only the opt-out, was rewritten through that subdomain to an opaque path that redirects to the real destination. Call to action, blog post, pricing page, all of them. The rewritten path encodes its destination the same way the opt-out token encodes a recipient: in a form only HubSpot can resolve.
The migration plan had the whole site launching on one day, apex and www together, with every HubSpot record repointed at once. Had the email subdomain moved with them, every link in every email already sent would have died at the same moment, and so would every link in the three nurture sends still on the calendar, each reaching up to about 1,063 enrolled contacts. The company would have mailed its own prospects three times with every button broken.
Every link in every email the portal had ever sent was rewritten through one subdomain. Move it on launch day and every call to action in three live sends goes dead.
The ruling was simple once the measurement was on the table. The email subdomain moves last. The site launches on the apex and www; the email subdomain stays on HubSpot through the final scheduled send. HubSpot keeps honoring its own tokens, records each opt-out natively, and a final pull of the portal’s suppression state after that last send carries the late opt-outs into the new platform. 3 See also 3 See Dies With the Portal: the portal-level unsubscribe history is readable only from a logged-in session, and it must be loaded into the new platform as suppression before a single subscriber. The final re-pull after the last HubSpot send is what carries the last opt-outs across.Read Dies With the Portal: Seven Things a HubSpot Export Will Not Give You Only then is the record repointed, and the new site takes over the old paths.
Two dates fall out of that. The last send is the last morning the nurture is scheduled to fire, not the contract date, because the nurture sends on a fixed weekday and the contract ends on a different one. The legal floor is 30 days after that send. The page outlives the floor by design, because nobody clears a two-year-old newsletter out of their inbox on a schedule, and a one-field page costs nothing to keep.
What the page cannot know, and the one thing it asks
Because the token cannot be decoded, the replacement page cannot know who clicked. It has to ask. CAN-SPAM allows a sender to ask for an email address and nothing more, and an address is the only identifier the new platform can act on. One field, one page, one button that unsubscribes that address from the company’s marketing email. The redirect from the old HubSpot path happens before the visitor sees anything, and the token is dropped at that redirect so it never reaches the page’s URL, the analytics tool, or a log line.
That last point is a design constraint, not a nicety. The token is a recipient identifier. On the new host, the legacy paths are to return a 301 to the clean page with the query string removed, and that has to be done in code rather than in the host’s redirect rules, because those rules preserve the query string by default and would carry the token straight into the analytics stream.
The page is designed to be served on all four hostnames HubSpot had ever answered for: the apex, www, the email subdomain and a resources subdomain. Doing all four costs nothing and covers whichever host an old email happens to use. Every other path on the email subdomain, which is to say every old tracked link, is to get a 301 to the homepage with the query stripped, because the tracked-link paths cannot be decoded either. HubSpot’s own identity parameters, the ones it appends to every tracked link, are stripped before any analytics event fires.
The design, in plain words
What follows is the specification we wrote for this exit. Read it as a design to copy, not as a report on a finished build: on this portal the page is part of the cutover work, and the cutover is not done.
No challenge. The spam gate is a honeypot field and a per-IP rate limit, and nothing visible. A bot-check widget is an extra step, and the law does not allow an extra step. The worst abuse an open form invites is someone unsubscribing an address that is not theirs, which is harmless and reversible, and a bot that fills the honeypot gets the same success page while nothing is written.
One response for every outcome. Whether the address was on the list, was never on the list, or came from a bot, the visitor sees the same sentence: done, this address will not receive the company’s marketing email. Identical text means the page cannot be used to probe who is a customer. An address that was not on the list is recorded in the new email platform as unsubscribed anyway, so that no later import or form can subscribe it by accident. The CRM, if it holds the person, gets an opt-in flag set to false with a timestamp and a source naming this page. If it does not hold the person, it is left alone, because a CRM is not a suppression list and the email platform is. 4 Editor's note 4 HubSpot lets a recipient opt out of one subscription type and keep others. The replacement here has a single marketing audience, so the page collapses any opt-out into unsubscribe-from-all. That is the stricter reading, and it is the one the law requires to be possible on a single page. Per-topic preferences are a feature of the new platform, not a compliance requirement.
It works with JavaScript off, because a one-page rule is only met if the page works for everyone who reaches it. It says in plain words that transactional mail is unaffected, that the request takes effect immediately, and whom to write to otherwise.
If the write to the email platform fails, the visitor still sees success. The request is already committed to a queue the moment it is submitted, and a failed write sits in a dead-letter view and retries. Ten business days is ample room for a retry. What is not acceptable is a visitor seeing an error, trying again, and giving up.
One-click unsubscribes, the kind a mail client offers from its own interface, are a separate path. 5 Editor's note 5 Mailbox providers also honor a one-click unsubscribe sent as a POST from the mail client, under the List-Unsubscribe-Post header described in RFC 8058. Where HubSpot points that header is visible only in a received email’s full headers, not in the portal. A POST to an old path gets a 200 and a counter, because without a decodable token there is nobody to unsubscribe, and the response must neither fail nor pretend.
Nothing alerts anyone per submission. An unsubscribe is not a lead. A weekly count is enough.
The obligation that needs a name
The opt-out is the obligation that can be discharged in code. There is a second one that cannot.
Among the portal’s workflows was one that deleted third-party enrichment data on request. Our review of the automation estate had a line for it that is worth quoting: this one “is not a feature, it is a GDPR/DSAR obligation”. It does not leave with HubSpot. The company has a live geographic exclusion rule, which means it has non-US contacts, and someone has to be able to receive a deletion request and act on it from the day after cutover, whichever vendor the enrichment data turns out to have come from.
Every other open question in the migration had a shipping default. This one did not. The architecture notes record it as the single item with no fallback: it needs a named person to own it. Not a workflow, not a form, not an agency. A person at the company whose name is written next to the obligation, with a documented process they can follow without a HubSpot seat.
The same is true, in a smaller way, of the 10 business days. The page handles the normal case automatically. If the email platform is down for a week, or a request arrives by reply to an old email instead of through the link, a human has to notice and act inside the window. The weekly count is where they notice.
Every other open question in the migration had a shipping default. This one did not. It needs a named person to own it.
What you get for doing this once
A compliance tail handled in code, once, instead of a complaint handled by a lawyer, repeatedly. That is the floor. The ceiling is more interesting.
The opt-out becomes a record the company owns. In HubSpot, consent was a billing flag with a timeline you could read only from a logged-in session. After the move, every unsubscribe carries a timestamp and a source, including the ones that arrive through a two-year-old email next spring. When a customer, an auditor or a regulator asks whether the opt-out mechanism worked on a given date, the answer is a row, not a reconstruction.
The sending domain starts clean and stays clean. No spam button pressed in frustration at a dead link, no reputation spent on an old email’s broken footer. The consent trap that most migrations fall into, re-subscribing people who had opted out, is closed from both ends: the suppression history goes in first, and the late opt-outs have somewhere to land.
The subdomain rule becomes reusable. Email domain last, after the last send, after the last suppression pull. It is a sequencing decision that applies to every HubSpot exit, and knowing it in advance is the difference between a launch day that is boring and one that mails 1,063 people a set of broken buttons.
And the company ends up with its obligations written down. Which link, which host, which page, who owns deletion requests. None of that was written anywhere in the portal. All of it exists only because the exit forced the question.
The order of operations
Read the portal before you touch DNS. Which subdomain the opt-out links use, whether it is also the click-tracking domain, and how many emails have it as their active domain. On this portal the answer was all of them. Have someone forward a received marketing email with full headers, because where the one-click header points is visible nowhere else.
Schedule the email subdomain’s move for after the last scheduled send and after the final suppression re-pull, and put it on the same change list as the rest of the cutover so it is not forgotten. If a sequence is still running, decide whether it is switched off early or allowed to finish, because that decision sets the date.
Build the one-field page before the site launches, and serve the old paths on every host HubSpot ever answered for. Strip the query string in code. Test that a click on an old link, with a HubSpot-style token, ends on the clean page with nothing in the URL, and that no analytics event ever carried the token.
Write a name next to the deletion obligation. Then keep the page. The 30 days are the floor; the inboxes are the real horizon.
If you are still deciding whether to leave, the data you think you own is the piece to read first, because the opt-out token is a small example of a large pattern. If you have decided, the migration guide covers the content, the forms and the CRM, and the renewal calendar sets out what must happen before the contract ends. This piece is the item on that calendar that keeps running after it.
The research is free. So is the diagnosis. 60 seconds →