The Joomla router will set up the "option", "view" etc input parameters once it's parsed the SEF URL. So you just have to overwrite those values using the input set method (https://api.joomla.org/cms-3/classes/Joomla.CMS.Input.Input.html#method_set). Then your component/view will be executed instead.
So define a group="system" plugin which listens for the ...
I won't pretend to believe that this answer will completely resolve your problem, but I do see a couple things to be fixed up.
if (!strpos($id, ':')) is not advisable practice even if it does what you intend to do. To check if a substring exists within a string you should be performing a strict boolean check on false (either !== or ===)
if (strpos($id, ':'...
Since 3.9 there's Joomla\CMS\Router\Route::link() method which takes client (site or administrator) as first argument.
$link = 'index.php?option=com_content&view=article&id=1';
echo '<a href="' . JRoute::link('site', $link) . '">Test</a>';
If you have the article object available, you should use ContentHelperRoute::getArticleRoute() and ...
So... I made this far too difficult for myself.
The answer is that I had a space in my code, right after the opening img src=" this was causing the Joomla SEF plugin to prefix my domain URL in the space.
console.log('<img src=" '+url+' ">');
Hope this saves someone else a few ...