A large grid of icons and names of online sharing services with a huge Share button in front.

How to use AddToAny as a fallback for the Web Share API

Almost all websites feature a row of brightly colored sharing-buttons at the top or bottom of each page. These buttons keep the big social networks at the front of people’s minds while also enabling the same networks to spy on people across the web.

The buttons even pose a legal risk to website owners. More than 400 000 websites still proudly feature sharing buttons for long-gone social-sharing networks of the past like Digg, StumbleUpon, and Google+.

Surely there must be a better way! The new Web Share API draft gives websites access to the native sharing tools built-in to modern operating systems. The draft API is only supported by Google Chrome version 61+ on Android, and Safari 12+ on iOS and macOS. However, it holds a promise of being a more privacy-preserving and unified user experience for content sharing.

Rather than being a promotional/spying-tool, the operating system’s native sharing tool is extendable and personalized. It enables quick sharing to the apps and services the user has installed and actually uses, without leaking personal data about their browsing habits to other parties.

It’s not limited to just social networks. The native share dialogs support other types of apps like reading-lists, note-taking, email, and more.

It’s really easy to implement the Web Share API. I’ll get back to a complete implementation example later in the article. However, one big unanswered question remains: what do you do with unsupported web browsers?

A common fallback is to hard-code fallback links to share the content on either Facebook or Twitter. I don’t want to push my readers to any of these services. Especially not after they’ve clicked on a somewhat ambiguous “Share” button.

Another option is to waste time to provide a custom share dialog listing different options. This often involves including a large JavaScript library or a completely custom implementation. This quickly adds complexity and requires ongoing maintenance. You don’t want to become one of those websites that waste valuable space promoting a dead social network!

A rather obvious choice is to outsource to one of the many multi-network content sharing services. However, the leading providers like AddThis and ShareThis are slow to load, collect a large amount of personal data about readers, and require a lot of work to integrate.

AddToAny has sharing widgets similar to the ones offered by AddThis and directly by the different social networks. However, it also has an easy-to-integrate API endpoint with a good selection of sharing services. The service is built with privacy-by-default.

AddToAny’s privacy policy is a joy to read compared to its competitors, and most other online services. It’s to the point and takes less than two minutes to read.

You don’t need to load any third-party JavaScript or send any signals to AddThis. You can simply open a window and link directly to their sharing-sheet with your link built-in. Using this implementation, AddToAny only collects limited anonymized data with Google Analytics (the title of the page being shared), and with the service the user chooses to share data with.

Let’s get back to the Web Share API. You can easily feature-test for support by testing for navigator.share. If present, you provide it an object with the title and url you want to share.

When the feature-test fails, you can fallback to opening a window with AddToAny. The page to open must follow this URL pattern:

https://www.addtoany.com/share#url=&title=

You can supply the two parameters with hardcoded values, or URL-encoded values from document.location and document.title.

You can get higher-quality data sources of existing metadata elements, if your websites deploy them. E.g. you can use the canonical link and the meta title as shown below:

document.querySelector(
  'link[rel~=canonical]').href;
document.querySelector(
  'meta[name=title]').content;

You may have noticed that AddToAny’s use of a fragment to parse variables means that these aren’t sent to AddToAny’s servers. (Except by misbehaving HTTP clients.) These values are read client-side on the sharing page; minimizing the data that is shared with AddToAny

The following example shows a complete implementation of the Web Share API and includes a fallback that opens a new window to sharing with AddToAny:

if (navigator.share) {
  navigator.share(
    {
      title: document.title,
      url: document.location
    }
  } else {
    var share_uri = `https://www.addtoany.com/share#url=${encodeURI(document.location)}&title=${encodeURI(document.title)}`;

    var wo = window.open(
      'about:blank',
      null,
      'height=500,width=500'
    );
    wo.opener = null;
    wo.location = share_uri;
    ev.preventDefault();
    return false;
  }

You’d call this in response to a click event on your share button design. The complications around window.open are there to properly mitigate tabnabbing.

People can manually customize the list of services shown in AddToAny. The service doesn’t make any personalizations on its own. The default list places Facebook and Twitter on top, which should cover the most popular services. It also contains a wide variety of services including Instapaper, Blogger, Mastodon, and 85 others.

AddToAny doesn’t optimize which services are places on the top of the list by regions. E.g. it doesn’t move Sina Weibo and RenRen to the top of the list in China, or VKontakte to the top in Russia. This would be a nice feature to have.