Skip to main content

Backlinks

Backlinks are surprisingly hard to get right in a single-page app, and we regularly encounter issues where clicking a backlink or button doesn't take the user to the expected place.

This guide is meant to help you diagnose common issues, and help you fix them quickly.

info

This document should give you a headstart fixing backlink issues, but if you find yourself wrestling with them regularly, it's a good idea to familiarise yourself with the API documentation and setup guide of the useBackLink hook, which should help you understand how it works at a deeper level.

Unfortunately, this is normal. The backlinks in our apps are not the same as the browser's back button, and they lose their history after a page refresh. (This is a technical limitation – we did consider storing the backlink history in the user's localStorage, but since that storage works across multiple browser tabs, it's not a straightforward solution and could easily break expected behaviour.)

In these cases when there is no history, the "fallback" location that has to be defined for every backlink will be used, so make sure that it is set to the most natural destination when there's no other context.

This used to be a very common issue for us: A user is automatically redirected to a new page, but when they click the backlink, it takes them to the previous page, which automatically redirects them again: The user is stuck in a loop!

Luckily, our BackLinkManager offers a way of dealing with this that's already set up to work in our /hub and /admin apps. (Check out the docs if you need to set this up from scratch in another app.)

The solution is to find the page that contains the redirect, and to add the property wasRedirected to the location state of the redirect target:

history.replace('/login', {wasRedirected: true});

Once that is done, our BackLinkManager knows that the previous URL contains an automatic redirect, and will not navigate back to it.

info

Location state is a feature of React Router that allows attaching arbitrary data to a location without it being contained in the URL (unlike a query parameter, for example).

This means that this technique will not work for redirects that reload the entire page and don't use our client-side router. But since a page refresh resets our BackLinkManager anyway (as mentioned in issue #1), no special handling is required, and the fallback link will be used.

This is a common issue when a backlink exists on a page that serves as the host for multiple tabs or dialogs that are also controlled by the URL (as they should be!)

The solution to this involves two steps:

  1. Reflect the hierarchy of all sub-pages or dialogs opened from this page in the URL. For example, if the path of the host page is /profile, the paths of all subpages should start with /profile, too – for example: /profile/history.

  2. Once requirement 1 is fulfilled, find the useBackLink hook that powers the affected backlink, and define a base path for it. The basePath should match the URL of the host page:

    const backLink = useBackLink({fallback: '/', basePath: '/profile'});

Once that is done, any pages nested within the host page will not be considered as backlink destinations anymore.

The docs of the useBackLink hook go into more detail on this functionality, and also describe how to exclude specific URLs from the backlink history. You can also define multiple base paths by passing in an array of paths.

Feedback

Did you encounter another issue around backlinks that wasn't covered here? Let me know and we can add it!