Redirect Page for External URLs

Hey there! I would like to redirect all external links (or if not possible to filter, all links) to e.g. exit.website.tld/?page={{URL}}
Is this possible with Discourse? If not, is there a Plugin for that? I already searched but couldn’t find one with the search queries I used.
So similar to how Steam does it. (Example)

2 Likes

I had been thinking about this as well; I wanted to append the Internet Archive save URL to all external links, and let’s be honest: it would be cool to set by category.

I figure there is some filter thing to be done by a plugin, but folks do things with theme components that seem to bend the rules on data manipulation, so if this isn’t currently possible, how would folks approach adding it: plugin or theme component?

1 Like

We view this as kind of a user-hostile feature to have (along the lines of “forum signatures”), so it’d need to be a plugin. Not sure if it could be done in a theme component?

I’ve seen this request before in the context of safety, as in

:scream: oh noes! you’re about to visit a HYPERLINK to a WEBSITE! Have you prepared yourself for INCREDIBLE DANGER?!?!

and I guess that could make sense in some extremely rare contexts in some extremely rare communities… uh… I guess?

5 Likes

I run a category for archiving websites. Our use case is super-specific/lazy. :slight_smile:

Also, I think of the web archive proxy as being similar to grabbing a copy of an image in a message, but again, I run a category for archiving websites. :nerd_face:

5 Likes

It’s fair, there may be some valid use cases, I’m just out here fighting for the users, man…

OpenTerrificEquestrian-size_restricted

4 Likes

In my opinion, it might actually be a safety thing, because of course here on the Discourse Meta Forum or on some Programming Forums people know how to differenciate URLs etc., but on Forums which aren’t so focussed on tech (especially Forums for non-tech Jobs, Schools etc.) many people might not notice if they’re on a site which looks the same but has a different TLD or maybe even a completely different Domain Name.
And while this of course may be user-hostile for some Forums, nobody says it has to be enabled by Default. You could just make it like a check mark which would then use a Page by DIscourse itself or link a custom Page directly.
In my opinion this is more of an essential feature which should be directly in Discourse, but of course, that’s just my own opinion.

Jeff has made it clear that this will need to be a plugin (unless it can be done in a theme, which seems likely). History suggests that if you develop the login and hundreds of sites want it, including dozens of enterprise customers, it should become an official plugin in only a few years.

But, if it’s possible to do in a theme, which I think it might be, then arguably discourse already supports the feature, you just need a theme to do it! You can check out Developer’s guide to Discourse Themes or post in #marketplacewith a budget. My guess is that it’s at least $1000 but I could be wrong.

3 Likes

While I don’t have experience with Discourse Themes etc., I have basic experience with JS and HTML. Something like this shouldn’t be more than 10-20 Minutes of Work. Why would that need a budget of $1000?

If you can do it in twenty minutes then you should have done it already. I’m still pretty bad at javascript and ember, maybe it’s much easier than I think. I think that it’s several hours work.

Please post a link to your theme! I can’t wait to see it.

2 Likes

After around 5 Minutes I got working JS Code (which still needs some improvements, but it works; 10 lines by the way)
The only thing I need to find out now is how to run this code after page load…

2 Likes

Awesome! Glad it was so easy! That stuff takes me an insane amount of time. I’m usually better as guessing how long it should take.

1 Like

In general it’s just checking if you’re on an Article Page, looping through all <article> Tags, finding the actual Tag of the Content in it, looping through all <a> Tags in there and if their href isn’t an official site (using some basic RegExp for that) adding the Exit Page URL in front.
But I’m still struggling at finding out how to run the JS Code after the Page has loaded and all dynamic content (such as Posts) have been loaded. A temporary solution would be to just run the Code after 1-2 seconds, but that isn’t that great and for some people it might take more than that to load…

2 Likes

It can certainly be done as a theme component, but keep in mind it will have to be a plugin if you want it to also affect the crawler view.

4 Likes

What you’re looking for is called a post decorator. It’s a hook that allows you to run scripts before each post is rendered. It’s a part of the plugin API.

Now, regarding what you want to do (redirect all external links). I don’t think adding that much friction is a good idea, so I can’t help you with that - plus you already figured that bit out. That said, here’s a commented example of how you can create a setup that targets all external links in posts

This goes in the header section of your theme / theme component

<script type="text/discourse-plugin" version="0.8">
  // store the hostname so we can reuse it.
  const siteHostname = location.hostname;
  
  // let's create a decorator to do this in every post
  api.decorateCooked(
    post => {
      // does the post have links?
      const links = [...post[0].querySelectorAll("a")];
      
      // no links, bail.
      if (!links.length) return;
      
      // We have links, let's filter them and only grab the ones that are external
      const externalLinks = links.filter(
        link => link.hostname !== siteHostname
      );
      
      // if we have some external links, let's do some work. For example, we can
      // add a class to each external link like so.
      externalLinks.forEach(link => {
        link.classList.add('external-link');
        // do more work here.
      });
    },
    // we give our decorator an id to prevent memory leaks.
    { id: "external-link-decorator" }
  );
</script>

Again, redirecting users is too much friction and will get annoying real fast. So, I would consider another approach, like maybe adding a subtle icon next to external links and teaching your users what it means instead?

4 Likes

I think this use-case is much better served by a plugin or external integration (using a post create/edit webhook) that ensures all linked sites are properly preserved, whether or not someone clicks on them.

3 Likes