Craig Buckler Freelance UK IT consultant specialising in HTML5 webby stuff.

How to improve social engagement with the Web Share API

7 min read 2161

In this tutorial, we discuss:

  • Why social media buttons could be harming your website
  • Alternative social media engagement options, and
  • How the Web Share API can be used to share data with social media and/or other apps on your device

Social media buttons

Most popular social media platforms provide simple buttons you can add to any web page.

facebook share button

Facebook “like”, Twitter tweets/retweets/likes, LinkedIn share, and more. The buttons allow users to share and discuss your content … in theory.

The reality is somewhat less beneficial.

Share buttons have low engagement

Social sharing buttons are rarely used. It will depend on your site, but most will be lucky to achieve a 1% click-rate. The GOV.UK website published their sharing statistics from 2014 shortly after the site went live:

  • Overall, just 0.21% – or 1 in 476 users – clicked a share button
  • Mobile users were twice as likely to use a share button as those on desktop

Moovweb reported a similar click rate of 0.2%. Visitors were twelve times more likely to click an advertisement!

Sharing systems offer poor and inconsistent UIs

Every social media site has a different button that must be added to pages on your website.

The submission processes can also be confusing for users. Forms are inconsistent, terminology can vary, and the user interfaces can be awkward – especially on mobile devices.

Supporting every social media system is impossible

Your Facebook, Twitter, and LinkedIn buttons are no good to someone who wants to share on Pinterest! Adding every social media option is impractical and even a third-party service such as AddThis may not cater to popular systems across an international audience. Some services, such as Instagram, do not provide sharing facilities.

Share buttons affect site performance

Most sharing buttons can be added to your site with a few lines of code. Unfortunately, that innocuous-looking HTML has a hidden cost. Facebook’s share button alone downloads 786Kb of code (216Kb gzipped). Twitter adds a further 151Kb (52Kb) and LinkedIn 182Kb (55Kb).

You can assess the total size of sharing buttons on your site by opening the Network tab in your browser DevTools. Check Disable cache, enter a specific domain such as “facebook” in the filter, then refresh the page:

devtools network calls
The status bar at the bottom shows the number of requests, the total (compressed) data downloaded, the uncompressed file sizes, and load timings. The total of all third-party requests can be examined by entering “-domain:*.yourdomain.com” in the filter box.

Adding a few social media buttons will add significant bulk to your page weight. Processing a megabyte or two of JavaScript also has a detrimental effect on performance – especially on mobile devices.

Social sharing raises privacy concerns

Facebook’s JavaScript code is not sitting idle. Regardless of whether they click the button, all your visitors are being monitored across your site and other sites so their activities can be monetized. While this may not concern you, the social media sites collect user data for their benefit – not yours.

You may be legally compliant for data use

Does adding a “like” button make you liable for the use – or misuse – of personal data by a social network?

The European Court of Justice recently ruled that website owners can be held liable for data collection when using share buttons. A site is voluntarily sharing visitor information with a social network so it is considered a joint data controller.

Can you be certain those share buttons are legally-compliant in every territory where you operate? Are you sure the social media platform is acting responsibly?

Third-party JavaScript is a security risk

Adding a third-party <script> tag runs JavaScript with the same site-wide rights and permissions as your own code. That script can do anything – your security is only as good as the weakest provider.

British Airways was fined $232 million USD in 2018 when 500,000 customers had their names, email addresses, and full credit card information stolen during website transactions. The attack is likely to have originated from a third-party script which was modified possibly without the knowledge or permission of its supplier.

Social media companies will endeavor to prevent issues but no one is immune to security compromises.

Site engagement can be reduced

Social media platforms can only survive if they are used. Clicking a “share” button transports your visitor to that system where they will be encouraged to stay and be distracted from interacting with your brand or service.

URL-based social sharing APIs

Despite the risks and low usage, sharing buttons can increase exposure and offer some SEO benefits. Your next customer could learn about your service from conversations on Facebook, Twitter, LinkedIn, etc.

The problems with page weight, performance, privacy, and security can be significantly reduced by using URL-based share APIs. These do not require third-party JavaScript and will not track users unless they choose to engage with the buttons.

Any web page can be shared with Facebook by loading the URL:
https://www.facebook.com/sharer/sharer.php?u=${url}

or Twitter:
https://twitter.com/intent/tweet?url=${url}&text=${title}

or LinkedIn:
https://www.linkedin.com/shareArticle?mini=true&url=${url}&title=${title}

where ${url} is the page URL and ${title} is the title (typically the content of the HTML <title> tag).

Where available, visitors can also use a browser’s share facility to post URLs to other applications such as email, messaging, Pocket, WhatsApp, etc. However, that option is rarely obvious to users – until now…

The Web Share API

Following a few false starts, the Web Share API finally landed in Chrome 76 on Android, Safari 12.3 on iOS, and Safari 12.1 on Mac OS. When used, the browser hands information to the sharing facility on the host operating system. The OS knows which apps support sharing and passes data accordingly.

The advantages:

  • Sharing can be triggered from a page button rather than the less-obvious browser menu
  • Sharing becomes possible from full-screen Progressive Web Apps which hide the browser interface
  • A consistent UI and experience is provided. For example, Android users will see a sharing panel similar to this:

ui for android users
The sharing UI can be launched in reaction to a user click. The following JavaScript checks whether the Web Share API is supported then adds a button click handler which passes a ShareData object to navigator.share:

// is Web Share API supported?
if ( navigator.share ) {

  // share button click handler
  document.getElementById('share').addEventListener('click', () => {

    // share page information
    navigator.share({
      url: 'https://example.com/',
      title: 'My example page',
      text: 'An example page implementing the Web Share API.'
    });

  });

}

The ShareData object contains:

  • url – the URL being shared (an empty string denotes the current page)
  • title – the document title (perhaps the page HTML <title> string)
  • text – arbitrary body text (perhaps the page description meta tag)

navigator.sharereturns a Promise so .then() and .catch() blocks can be used if you need to perform other actions or react to failures.

Improved social sharing

The Web Share API has fairly limited support, especially on desktop browsers. For this reason, the following code provides a progressively-enhanced solution that implements a share button but also defines Twitter, Facebook, LinkedIn, and email options using the lightweight and secure URL-based APIs.

The full demonstration can be viewed on Codepen.io:

See the Pen
Simpler Sharing
by Craig Buckler (@craigbuckler)
on CodePen.


There is no standard share icon across desktop or mobile platforms, but the three-node graphic is recognizable and the text label should make it obvious. When clicked, it displays the standard OS share UI such as the Android example shown above.

The Twitter, Facebook, and LinkedIn buttons open the share URLs in a small pop-up window or another tab on mobile devices:

social share demo popup

Pop-ups are awful for user experience, but this is how the social buttons normally operate and it allows the user to return to the originating page.

Finally, the email button is a mailto: link which launches the default mail app.

HTML code

Any number of unordered lists with a class of “share” can be added anywhere within the HTML.

The first item shown below is the share icon. This is assigned a class of “webshare” and the link href targets “#webshare” so it can be identified.

All other list items define sharing URLs with ${url}, ${title}, and ${text} placeholders so the same code can be used on any page.

<ul class="share">
 
  <li class="webshare">
    <a href="#webshare">share</a>
  </li>
    
  <li>
    <a href="https://twitter.com/intent/tweet?url=${url}&amp;text=${title}">Twitter</a>
  </li>
 
  <li>
    <a href="https://www.facebook.com/sharer/sharer.php?u=${url}">Facebook</a>
  </li>
 
  <li>
    <a href="https://www.linkedin.com/shareArticle?mini=true&url=${url}&amp;title=${title}">LinkedIn</a>
  </li>
 
  <li>
    <a href="mailto:?subject=${title}&amp;body=${url}">email</a>
  </li>

</ul>

(SVG icon code is not shown to aid readability.)

CSS code

The sharing icons are hidden by default:

.share, .webshare {
  display: none;
}

The JavaScript (see below) appends a .social class to the HTML head when it runs. An additional .webshareapi class is added when the Web Share API is available. The CSS will, therefore, display the list and share button only when they are supported:

/* URL sharing is enabled */
.social .share {
  display: flex;
  flex-wrap: wrap;
}

/* Web Share API is supported */
.webshareapi .webshare {
  display: block;
}

Further properties define colors, styling, hover effects, etc.

/* basic share styling */
.share, .share li {
  list-style-type: none;
  padding: 0;
  margin: 0;
}

.share a {
  display: block;
  text-decoration: none;
  color: #fff;
  background-color: #557;
  border-radius: 1.5em;
}

.share a:hover, .share a:focus {
  background-color: #779;
}

JavaScript code

The JavaScript functionality is launched as soon as the DOMContentLoaded event triggers when the DOM is ready. The function extracts the following information from the page to create a pageInfo object:

  • url – extracted from the canonical URL where one is defined in the HTML <head> or the page URL otherwise
  • title – the document <title> defined in the HTML <head>
  • text – the description meta tag where available

The  <html> element has a .webshareapi class applied when navigator.share is available and another .social class applied to indicate the script is running. This triggers the CSS to display the links:

// web sharing detection
document.addEventListener('DOMContentLoaded', () => {
 
  'use strict';
 
  // get page information
  const
    html = document.documentElement,
    canonical = document.querySelector('link[rel=canonical]'),
    desc = document.getElementsByName('description'),
    pageInfo = {
      url: canonical ? canonical.href : location.href,
      title: document.title || '',
      text: desc.length ? desc[0].content : ''
    };
 
   // Web Share API support?
  if (navigator.share) html.classList.add('webshareapi');
 
  // social sharing enabled
  html.classList.add('social');

  //...
 
});

A handler event is defined which listens for click events on the whole document. When triggered, it checks if a share button has been clicked within a .share list and cancels the default action:

// click event
  document.body.addEventListener('click', (e) => {
    
    // on share button?
    let t = e.target.closest('A');
    if (!t || !t.closest('.share')) return;
    
    // cancel link
    e.preventDefault();

    // ...

  });

The code then checks whether the share link has been clicked and passes the pageInfo object to the Web Share API before returning:

 // Web Share API
    if (t.hash === '#webshare') {
 
      navigator.share(pageInfo);
      return;
 
    }

If any other link has been used, its href address is extracted and the placeholders are replaced with pageInfo information using the urlParse() function:

// social media link
    let popup, newUrl = urlParse(t.href, pageInfo);

The urlParse() function (at the end of the code) uses regular expressions to replace and encode strings:

// URL template parser
  function urlParse(str, token) {
    
    for (let t in token) {
      str = str.replace(
        new RegExp('\\$\\{' + t + '\\}', 'g'), 
        encodeURIComponent(token[t])
      );
    }
    return str;
    
  }

Finally, any http link handler is opened in a centered pop-up window measuring 600x600px or fitting within the available space on smaller screens:

// open popup
    if (t.protocol.startsWith('http')) {
     
      let
        sw = screen.availWidth || 1024,
        sh = screen.availHeight || 700,
        pw = Math.min(600, (sw - 40)),
        ph = Math.min(600, (sh - 40)),
        px = Math.floor((sw - pw) / 2),
        py = Math.floor((sh - ph) / 2);

      popup = window.open(
        newUrl,
        'social',
        `width=${pw},height=${ph},left=${px},top=${py},\
        location=0,menubar=0,toolbar=0,personalbar=0,\
        status=0,scrollbars=1,resizable=1`
    );
    }

Focus is set to the pop-up but, if this fails to open or a non-HTTP handler is required (such as mailto: links), the window location is set to the URL:

if (popup) popup.focus();
else location.href = newUrl;

Conclusion

The full demonstration can be viewed at Codepen.io.

The JavaScript above minifies to less than 1Kb of code and does not require a framework (it should be compatible with any). It permits sharing buttons to be added to your website without the performance, privacy, or security implications of those provided by social media companies.

 

 

Plug: , a DVR for web apps

LogRocket is a frontend application monitoring solution that lets you replay problems as if they happened in your own browser. Instead of guessing why errors happen, or asking users for screenshots and log dumps, LogRocket lets you replay the session to quickly understand what went wrong. It works perfectly with any app, regardless of framework, and has plugins to log additional context from Redux, Vuex, and @ngrx/store.

In addition to logging Redux actions and state, LogRocket records console logs, JavaScript errors, stacktraces, network requests/responses with headers + bodies, browser metadata, and custom logs. It also instruments the DOM to record the HTML and CSS on the page, recreating pixel-perfect videos of even the most complex single-page apps.

.
Craig Buckler Freelance UK IT consultant specialising in HTML5 webby stuff.

Leave a Reply