sudolabs logo

19. 9. 2023

10 min read

Share Visual Content from Web to Social Media without API or SDK

You know the struggle. When you want to share images, videos, or links to social media platforms from your web app, you often have to deal with different APIs or SDKs. And here's the ultimate way how to share visual content from the web app to any social media on your phone.

Oliver Dendis

Software Engineer

This adds significant implementation overhead to your codebase. You need to install new dependencies and manage them, repeating the process for each social media platform you want to support. Additionally, each SDK/API has its own implementation details, permission levels, and limited capabilities. While it may seem impossible to find proper solutions for implementing social media sharing options, the truth is that there are elegant ways to allow users on your web app to share visual content on platforms like Facebook, Instagram, Twitter, and more.

Before we start, it is worth mentioning that this solution is well-suited for mobile browsers due to its better support. However, the overall experience might be less satisfactory when using desktop browsers.

Image share problem

Let's consider a scenario where you want to enable users of your web app to share customizable images (e.g., with the user's name and photo) to Facebook. Unfortunately, the Facebook SDK does not support the direct sharing of images through its Share Dialog.


It only allows the sharing of links. So, if you want to share a unique image generated by the user to Facebook, it needs to be represented as a dynamic link with the <og:image> tag set to the URL of the image you want to share.

FB.ui(
{
method: 'share',
href: `${url}/${imageId}`, // dynamic URL which has <og:image> set to the image URL you want to share.
hashtag,
},
() => {} // callback
);

This solution has a couple of downsides. Firstly, Facebook treats your image as a link, so you still need to provide some content to avoid displaying a blank page when other Facebook users click on the link. Doesn't dealing with open graph tags and generating pages feel like overkill? Moreover, Facebook is one of the more generous platforms that at least offer a way to share something through their SDK. There are platforms that don't even provide a solution for image sharing.

But, there's an alternative! Let's forget about different SDKs and APIs and leverage the power of your device. You'll love it because you might have already used it without even realizing it! Have you heard of the Web Share API? The Web Share API is a browser built-in API that invokes the native sharing mechanism of the operating system and passes the provided data like title, text, URL, and files. If you provide an image in the files array, the share API will send the image to the underlying OS, opening the familiar share interface.

Here's a glimpse of what the UI for Instagram and Facebook look like:

The share interface offers multiple ways to share the image, including social media platforms


As you can see, the share interface offers multiple ways to share the image, including messaging apps and social media platforms like Instagram, Twitter, and Facebook.

After the user chooses their preferred social media platform, the detailed sharing options appeared.

To open the share interface on your phone, you can use the following code:

export function ShareFileButton({ file }) {
const shareData = {
files: [file]
};
const onClick = async () => {
try {
await navigator.share(shareData);
} catch (err) {
console.log("Something has failed", err);
}
};
return <button onClick={onClick}>Share some cool stuff</button>;
}

Here you can find the codesandbox with a provided solution:

Note: If you look at it with your desktop browser, you may see a message that you cannot share files. That means that your OS and Browser do not support this feature. Since the support is much better on mobile devices, I really recommend using a mobile browser to open this example


The navigator.share function accepts a single object as an argument. This argument object can contain fields such as title, text, URL, and files. The files field must contain an array of File objects, whereas the title, text, and URL should all be string parameters.

In the CodeSandbox example, we used a hard-coded image in base64 format. We converted it to a Blob and generated a File object from it. If you're creating dynamic visual content from HTML Canvas, you can generate File objects directly from it. If you're using HTML markup to create visual content for sharing as an image, you can utilize existing third-party libraries, such as html-to-image, to achieve this.

Limitations and how to deal with them

When working with the Web Share API, there are a few limitations and considerations to keep in mind. While the example above demonstrates a simple code snippet for opening the native sharing bar, simplicity does come with certain trade-offs.

OS and Browser support

Since the functionality relies on a Web API, its support can vary across different operating systems and browsers. Here is an overview of the current support:

When working with the Web Share API, there are a few limitations

Link to caniuse

To prevent failed sharing attempts, it's advisable to provide a fallback option for users whose current browser or operating system doesn't fully support the Web Share API.

You can check if the browser can trigger the opening of the share bar by using the navigator.canShare method. This method accepts the same arguments as navigator.share and determines the feasibility of sharing. If the user cannot share content, you can display a fallback screen to provide an alternative experience.

import { CannotShareFallback } from "./CannotShareFallback";
export function ShareFileButton({ file }) {
const shareData = {
files: [file]
};
const onClick = async () => {
try {
await navigator.share(shareData);
} catch (err) {
console.log("Something has failed", err);
}
};
const isShareable = navigator.canShare && navigator.canShare(shareData);
if (!isShareable) {
return <CannotShareFallback />;
}
return <button onClick={onClick}>Share some cool stuff</button>;
}

It's important to note that the canShare method checks the possibility of sharing based on the current sharing data. Therefore, it's possible that a user may not be able to share images but can still share links or other content types.

The support for this feature on desktop browsers is very poor, which can be restrictive in its functionality and therefore these checks could be handy.

The share bar should open only in response to user actions

The opening of the share bar should be exclusively triggered by a user's action, such as clicking on a UI element. This approach imposes limitations when:

  • You want to open the share bar without any user interaction, such as immediately after the page is loaded.

  • You need to await an asynchronous action before opening the share bar.

The first case is not very common, and from a UX perspective, it's not recommended to open the share bar right after the page loads since users don't expect it. Surprisingly, though, I managed to open the share bar in a useEffect hook after the sharing button was mounted, and it somehow worked.

The second case might be of more interest to you. In certain situations, you may need to perform an asynchronous operation before sharing, such as fetching data from an external source or generating a file asynchronously. If you've already tried awaiting asynchronous operations before sharing and it worked, you might be surprised. The truth is, you don't need to trigger the opening of the share bar immediately after the user interaction, but it should occur within the transient activation period. Transient activation is the time window during which the browser considers an operation as a result of user action. It starts right after the user takes an action and ends after a defined timeout. If the asynchronous code finishes within the transient activation timeout, the opening of the share bar will be successful. However, if it takes longer than the timeout, the opening will fail. In my experience, it worked well as long as the async operation took less than 5 seconds (tested on macOS 13.4, Chrome v113). Any duration longer than 5 seconds resulted in the failure of opening the share bar options.

Nevertheless, relying on the duration of an asynchronous operation is generally not recommended. It is not considered a good practice to await asynchronous operations before opening the share bar. Moreover, from a UX perspective, opening the share bar immediately after the user's click is a more expected behavior. This means you should ensure that all the necessary data for sharing are ready before the user clicks on the share button.

As a general recommendation, I suggest displaying the sharing options only when the data for sharing are fully prepared and you are certain that sharing is supported.

Limited to secure context

It's important to note that the Web Share API requires a secure context to work properly, meaning it needs to be served over HTTPS. In production environments, having HTTPS is standard practice, and the Web Share API will work seamlessly. However, during local testing with a mobile browser and accessing localhost through a local IP, you may encounter limitations since it's not considered a secure context.

For simple proof of concept and lightweight demos, I recommend using web-based code playgrounds like JSFiddle or CodeSandbox. These platforms usually provide a convenient environment to showcase the functionality of the Web Share API.

The trickiest part in implementing the Web Share API is often not the sharing itself, but rather the generation of content that will be shared. This content generation process should be easily debuggable in your local environment, allowing you to test and fine-tune the sharing feature effectively.

Not controlled by your code

One important aspect to consider with the Web Share API is that it provides a simplified solution by relying on the underlying operating system for the sharing process. While this simplicity is convenient, it comes with a trade-off: you have limited control over the sharing process.

Due to the nature of the Web Share API, it's not possible to define a specific list of apps for sharing or customize the order in which they appear in the sharing bar. The decision of which apps are available and their arrangement is determined by the user's device and the installed apps on that device. As a developer, you have no direct control over these aspects.

Furthermore, once the sharing action is performed successfully, you won't receive detailed information about which specific app was used for sharing. This lack of information can limit your ability to track or analyze sharing activities on a granular level.

When using the navigator.share function, it returns a Promise<void>, which requires handling with await and utilizing a try/catch block for error handling. However, the behavior of the promise resolution can vary depending on the sharing app.

For some sharing apps, the promise may resolve immediately after the user selects an app, regardless of whether the sharing process is completed or not. On the other hand, some apps may only resolve the promise after the user completes the sharing process, ensuring that the content is shared successfully, so if the content is not shared, the promise is rejected.

So, in summary, if the promise is resolved, you cannot be really sure that the content was shared. On the other hand, if the promise is rejected, you can be certain that the content was not shared.

It's important to note that when the promise is rejected, the error message provided is often generic and lacks specific details about the underlying cause of the rejection. This limited information makes it challenging to precisely identify the reasons behind the rejection and troubleshoot any issues.

Summary

In summary, the Web Share API is a great option for adding sharing functionality to your web application. However, it's important to consider the specific use case and limitations of the API. Here are the scenarios in which I would recommend using the Web Share API:

  1. Testing/demo/proof of concept: If you need a quick way to demonstrate the sharing feature to your users or gather feedback, the Web Share API can provide a working demo without the need for implementing different SDKs or APIs.

  2. Non-essential sharing feature: If sharing is not a core or critical feature of your product, but rather a nice-to-have improvement, the simplicity of the Web Share API makes it a suitable choice.

  3. Mobile-focused web apps: The richness of sharing options is often more prominent on mobile devices due to the availability of various mobile apps and much better support on mobile browsers. If your web app primarily caters to mobile users, the Web Share API can offer a satisfactory sharing experience. For desktop users, you can always consider implementing sharing through other SDKs and APIs if necessary.

Despite the limitations, I have personally implemented the Web Share API in recent projects that met these requirements. Its ease of implementation and simplicity outweighed the limitations in those specific cases. If your app doesn't heavily rely on sharing content and the above criteria apply, I would recommend giving the Web Share API a try.

References:

https://developer.mozilla.org/en-US/docs/Web/API/Web_Share_API
https://developer.mozilla.org/en-US/docs/Glossary/Transient_activation
https://developer.mozilla.org/en-US/docs/Web/Security/Secure_Contexts
https://caniuse.com/web-share

Share

Let's start a partnership together.

Let's talk

Our basecamp

700 N San Vicente Blvd, Los Angeles, CA 90069

Follow us


© 2023 Sudolabs

Privacy policy
Footer Logo

We use cookies to optimize your website experience. Do you consent to these cookies and processing of personal data ?