Skip to main content

External Link Treatment

Manually setting target="_blank" on every external link in Webflow is tedious and easy to miss, especially in CMS rich text content where you have no control over individual link attributes. This snippet scans all anchors on the page at load time and applies the correct attributes to any link pointing off-site.


Page Settings script

Add to Page Settings → Custom Code → Before </body> (or Site Settings → Footer for site-wide coverage):

<script>
(function () {
var host = window.location.hostname;
document.querySelectorAll('a[href]').forEach(function (link) {
var href = link.getAttribute('href');
if (!href || href.startsWith('#') || href.startsWith('/') || href.startsWith('mailto:') || href.startsWith('tel:')) return;
try {
var url = new URL(href);
if (url.hostname && url.hostname !== host) {
link.setAttribute('target', '_blank');
link.setAttribute('rel', 'noopener noreferrer');
}
} catch (e) {}
});
})();
</script>

With optional icon

Appends a small ↗ indicator after external link text so users know they're leaving the site:

<script>
(function () {
var host = window.location.hostname;
document.querySelectorAll('a[href]').forEach(function (link) {
var href = link.getAttribute('href');
if (!href || href.startsWith('#') || href.startsWith('/') || href.startsWith('mailto:') || href.startsWith('tel:')) return;
try {
var url = new URL(href);
if (url.hostname && url.hostname !== host) {
link.setAttribute('target', '_blank');
link.setAttribute('rel', 'noopener noreferrer');
if (!link.querySelector('.ext-icon')) {
var icon = document.createElement('span');
icon.className = 'ext-icon';
icon.setAttribute('aria-hidden', 'true');
icon.textContent = ' ↗';
link.appendChild(icon);
}
}
} catch (e) {}
});
})();
</script>

Style .ext-icon in Webflow's global CSS (Site Settings → Custom Code → <head>) to adjust the size, colour, or spacing of the indicator.


Notes

  • The try/catch around new URL() silently ignores any malformed href values that would otherwise throw.
  • Relative paths (/about, ../services) are skipped because they always stay on the same domain.
  • mailto: and tel: links are explicitly excluded — opening them in a new tab would be confusing.
  • rel="noopener noreferrer" is the correct combination: noopener prevents the new tab from accessing window.opener; noreferrer additionally suppresses the Referer header.
  • Runs at page load — links added dynamically after load (e.g. from CMS-rendered components via JavaScript) won't be caught. Run the function again after any dynamic content loads if needed.