Every developer knows the most dangerous phrase in software: "it's a 5-minute task."
Here's mine.
The task
At some point in the user flow: user clicks a button → open a new tab → continue there. That's it. That's the whole ticket.
const handleClick = () => {
window.open(url);
};
Ship it. Works everywhere. Well — "works in Safari" is always a bold claim, but even Safari behaved. I mentally closed the ticket and moved on with my life.
✅ THE HAPPY TIMES
[ user click ] ──► window.open(url) ──► 🗔 new tab opens
Then came The Change Request
"Small thing: before opening the new tab, fire an HTTP request, wait for the response, and then open the tab."
Sure. Small thing. One await, what could possibly go wrong:
const handleClick = async () => {
await fetch("/api/track-the-thing");
window.open(url); // 🚫 blocked
};
And that's where the browser said: no.
❌ AFTER THE CHANGE REQUEST
[ user click ] ──► fetch() ──► ⏳ await ──► window.open(url) ──► 🚫 POPUP BLOCKED
│
└── user activation expired here
Why browsers hate this
Turns out this is not a bug — it's policy. Browsers only allow window.open() as a direct result of a user action. The click gives you a short-lived "user activation" token, and the moment you go async and wait for a network response, that trust window slams shut. From the browser's point of view, a tab that opens after some background activity is indistinguishable from popup spam from 2005.
So the rule is brutally simple:
click ──► window.open ✅ works
click ──► anything ──► open ❌ doesn't
(Safari, as the strictest bouncer at this club, enforces it with particular enthusiasm.)
The workaround graveyard
I honestly don't remember every hack I tried — it's a blur of tab-related grief. There are known tricks (like opening a blank tab synchronously on click and redirecting it once the response arrives), but every single workaround failed the most important review of all: the business said no. Blank tabs flashing at users apparently don't scream "premium product experience."
So we did the mature engineering thing: abandoned the idea entirely and redesigned the flow to not need a new tab at that point.
Sometimes the best fix for a browser restriction is to stop arguing with the browser.
👉 What's your "5-minute task" that turned into a multi-day negotiation with browser policies?
Fought the popup blocker and lost?
Share your story — especially your own "5-minute task" that spiraled. I need to know I'm not alone in this support group.