Open External Links in a New Tab in Joomla

Keep visitors on your Joomla site by opening external links in a new tab and marking them nofollow, all at once, using one PHP snippet.

Open External Links in a New Tab in Joomla
Heads up! This article contains PHP code and is intended for developers. We offer this code as a courtesy, but don't provide support for code customizations or 3rd party development.

You link to a supplier, a news story or a partner, and the visitor clicks away from your site for good. Joomla has no global setting to open external links in a new tab or mark them nofollow.

The editor lets you set both, but one link at a time, and every link already in your old articles keeps opening in the same tab. You can fix every external link on your site at once with one PHP snippet in Code Snippets.

The PHP snippet code

Right before Joomla sends a page to the browser, the snippet finds every link that points to another domain and adds target="_blank" and the rel values you choose. It skips links to your own site, mailto: and tel: links, anchors like #top, and links inside scripts and form fields.

use Joomla\CMS\Factory;
use Joomla\CMS\Uri\Uri;

// Open external links in a new tab.
$newTab = true;

// Values added to the rel attribute of external links.
$rel = ['nofollow', 'noopener'];

// Other domains you own. Links to them and their subdomains stay as they are.
$ownDomains = [
    // 'myshop.com',
];

// Do not edit below.

$app = Factory::getApplication();

$updateLinks = function () use ($app, $newTab, $rel, $ownDomains)
{
    $document = $app->getDocument();

    if (!$document || $document->getType() !== 'html')
    {
        return;
    }

    // Your site's domain counts as your own, with or without www.
    $host         = Uri::getInstance()->getHost();
    $ownDomains[] = preg_replace('#^www\.#i', '', $host);
    $domains      = implode('|', array_map('preg_quote', $ownDomains));
    $ownHost      = '#(^|\.)(' . $domains . ')$#i';

    // Every opening <a> tag, plus whole <script> and <textarea> blocks,
    // so the links inside those stay as they are.
    $blocks  = '<(script|textarea)\b[^<]*+(?:<(?!/\1>)[^<]*+)*+</\1>';
    $pattern = '#' . $blocks . '|<a\s[^>]*>#i';

    // The domain of an absolute or protocol-relative link.
    $hrefDomain = '#\shref\s*=\s*["\']?(?:https?:)?//([^/"\'?\#:\s>]+)#i';

    $updateTag = function ($match) use ($newTab, $rel, $ownHost, $hrefDomain)
    {
        $tag = $match[0];

        if (!empty($match[1]))
        {
            return $tag;
        }

        // Skip links without a domain (relative, mailto:, tel:, #anchors)
        // and links to your own domains.
        if (!preg_match($hrefDomain, $tag, $href)
            || preg_match($ownHost, $href[1]))
        {
            return $tag;
        }

        // Keep any target the link already has.
        if ($newTab && !preg_match('#\starget\s*=#i', $tag))
        {
            $tag = substr($tag, 0, -1) . ' target="_blank">';
        }

        // Merge into an existing rel attribute, or add a new one.
        if (preg_match('#\srel\s*=\s*(["\'])(.*?)\1#i', $tag, $existing))
        {
            $current = preg_split('#\s+#', $existing[2], -1, PREG_SPLIT_NO_EMPTY);
            $values  = array_unique(array_merge($current, $rel));
            $newRel  = ' rel="' . implode(' ', $values) . '"';

            return str_replace($existing[0], $newRel, $tag);
        }

        return substr($tag, 0, -1) . ' rel="' . implode(' ', $rel) . '">';
    };

    $body = preg_replace_callback($pattern, $updateTag, $app->getBody());

    // On a regex failure, Joomla keeps the original page.
    if ($body !== null)
    {
        $app->setBody($body);
    }
};

$app->registerEvent('onAfterRender', $updateLinks);

The snippet edits each page as Joomla sends it, so your saved articles stay as they are. Unpublish it and every link goes back to how it was.

  • New tabs without nofollow: change $rel to ['noopener'].
  • Affiliate or paid links: Google prefers sponsored, so use ['sponsored', 'noopener'].
  • Other domains you own: add them to $ownDomains. Links to them and their subdomains stay as they are.

How to add this snippet

  1. Install Code Snippets if it isn't installed already.
  2. Log into your Joomla backend.
  3. Go to Components → Tassos Code Snippets.
  4. Click New.
  5. Enter a title, for example External links.
  6. Set Code Type to PHP.
  7. Set Insertion Method to Auto-Insert Locations.
  8. Set Location to On Page Load.
  9. Paste the code above into the editor.
  10. Add any other domains you own to $ownDomains.
  11. Click Save & Close.

Check that it works

  1. Open a page with an external link and view the page source.
  2. Search for the link.

It should now look like this:

<a href="https://www.example.com/" target="_blank" rel="nofollow noopener">

Links to your own pages stay as they were.

  • Links to your own site open in a new tab too. Your site answers on more than one domain. Add the other one to $ownDomains.
  • Nothing changed. Clear the Joomla cache (System → Clear Cache) and any page cache your host adds, then reload.
  • One link must stay in the same tab. Give it target="_self" in the editor. The snippet keeps any target a link already has.

Do this with other Tassos extensions

A new tab keeps your site open, but the visitor is still looking at someone else's page. With EngageBox, you can show a short popup the moment they click an external link, with a discount code, a newsletter signup or a "before you go" offer. You pick the pages and devices it shows on and how often, with no code, and EngageBox tracks how many visitors saw it and acted on it.

To link @mentions in your articles to X profiles, see Automatically Link Twitter (X) @mentions in Joomla Articles. To learn more about how PHP snippets work, read the PHP snippet docs.

Last updated on Oct 15th 2026 14:10