Redirect Category to External URL

Is there some native facility for redirecting categories to external URLs?

Customize >> Permalinks apparently does not support this use.

Why would you redirect a category to an external URL?
What’s the point of having the category if you only need a link?

1 Like

To have the link displayed as a category without going through all the necessary CSS fiddling to do so without it simply being a category.

The community where I’ll be doing this has a few related Discourse installs that each deal with a different set of topics; I want to more cleanly link them together by creating ‘categories’ that link from each site to each other site.

I briefly looked at doing this and it came down to two alternatives.

  1. Create the category with read only permissions for everyone and put the link into the ‘About this category’ page, maybe including a short paragraph why, like an ‘official’ external support site.

  2. Target and overwrite the link href in a theme component.

1 Like

I was afraid it would come down to that or doing a rewrite at the server level. I think I may just go with the (somewhat questionable) JavaScript option.

So, related issue: I’ve now implemented a redirect (using JavaScript), but… it works only on refresh, which is clearly suboptimal. At any rate, here’s the code I’m using:

$( document ).ready(function() {
	if ( window.location.href === "https://omnifora.com/c/redirect-politifora" ) {
		window.location.replace( "https://politifora.com/" );
	}
});

As should be obvious from the code, Omnifora is the primary site in this network and I am attempting to redirect a Politifora category on Omnifora to Politifora. I’ve already eliminated caching (browser, server, Cloudflare) as a potential culprit. Is there some quirk in Discourse that would cause this redirect not to trigger?

Yes, being a single-page-app the page only loads once, subsequent loads just replace the page contents. There is a page change API you can hook into:

1 Like

I’m sure this is the right way to accomplish the redirect, but I am not sure how to write the necessary code. I’ve tried the following and neither seems to work:

api.onPageChange((url) => {
	var targeturl = 'https://politifora.com/';
	if ( url === '/c/redirect-politifora' ) {
		$(location).attr('href',targeturl);
	}
});

and

api.onPageChange((url) => {
	if ( url === '/c/redirect-politifora' ) {
		window.location.replace( 'https://politifora.com/' );
	}
});

if you wanted a redirect this is the way to do it

api.onPageChange((url) => {
	if (url.includes('/c/redirect-politifora')) {
		window.location.replace('https://politifora.com/');
	}
});

however this is kinda slow and won’t run until the page has finished loading, which means users will still see the redirect category. i tried a second way, which is using jQuery to replace the links on the index or anywhere else this category appears.

api.onPageChange(() => {
  $(function(){
    $('a[href*="/c/redirect-politifora').attr(
      'href', 'https://politifora.com/'
    ); 
  });
});

with this you don’t need a redirect, because it modifies href attribute of every redirect-politiflora link in place.

2 Likes

Perhaps I’m missing something, but I tried each of those solutions (both imported from an external .js and dropped in as a customization) and was unable to get either one to work.

where are you inserting them, and do you have the correct script tags around them

1 Like

I tried both the header (using defer) and the footer (via Customize). When inserted via Customize, I had the code surrounded by <script></script> with type="text/discourse-plugin" set.

Update:

The window.location.replace option is currently live on Omnifora. I am using the following code (yes, I have tried a number of different matching options, but none of them seem to work):

Code Dropped into Customize

<script type="text/discourse-plugin" version="0.8.19">
api.onPageChange((url) => {
    if ( url === 'c/redirect/politifora' || url === '/c/redirect-politifora' || url === 'https://omnifora.com/c/redirect-politifora' || url.includes('/c/redirect-politifora') || url.match('/c/redirect/politifora') ) {
        window.location.replace('https://politifora.com/');
    }
});
</script>

Code as Rendered on Page

<script>Discourse._registerPluginCode('0.8.19', function (api) {

    api.onPageChange(function (url) {
        if (url === 'c/redirect/politifora' || url === '/c/redirect-politifora' || url === 'https://omnifora.com/c/redirect-politifora' || url.includes('/c/redirect-politifora') || url.match('/c/redirect/politifora')) {
            window.location.replace('https://politifora.com/');
        }
    });
});</script>

Given the wrapper that Discourse appears to have applied, it seems the code is partially working, but not performing its intended purpose (i.e., redirecting that category to Politifora). The live code (and its failure to function) can both be viewed on the aforementioned site (the target/affected category is currently at the bottom of the category list).

Is there some specific version of the API I should be using for this?

The following script achieves the intended result when added to </head> via Customize:

<script type="text/discourse-plugin" version="0.8.19">
api.onPageChange(() => {
	if ( window.location.href === "https://omnifora.com/c/redirect-politifora" ) {
		window.location.replace( "https://politifora.com/" );
	}
});
</script>
2 Likes

Thanks for this! I had a need for a set of subcategories to have one act as a redirect. Since my Customize already includes an onPageChange() check already (used to display a header on home page only) this should work as well, and thus is not hard-wired tot the full URL of the site:

<script type="text/discourse-plugin" version="0.8.19">
api.onPageChange((url) => {
       // Check if we're on the homepage 
        if (url === "/" || url === homeRoute) {
              // do custom stuff for home page
       } else if ( url=== "/c/redirect-politifora" ) {
             // category redirect
             window.location.replace( "https://politifora.com/" );
       } else {
             // do stuff on all other pages, if needed
       }
});
</script>
1 Like

Actually I did not use it, too much confusing delay while it showed the sub category browser re-directed elsewhere. But hey, I learned something.

You might find that less of an issue if you modify the route instead of relying on api.onPageChange() which seems to fire after the page is rendered.

See How to redirect an existing Disourse route in a theme component

1 Like