Add Share-to-Social Links to WordPress Posts

Add share to social links to WordPress posts

Learn how to add share-to-social network links to any WordPress content without installing a plugin. We’ll use some simple PHP to hook the content and inject the links & icons. The tutorial is easy to customise and you can add your own networks too.

importantMake sure you’re using a custom child theme so you can edit “functions.php”.

Sharing links

Define the problem

As with any project, the first thing we need to do is define the objective. In this case, we want to add share-to-social buttons to the end of posts, pages, products or any other content we want…

  1. Choose which post types have the share-to-social links. Default should be “posts”.
  2. Start with Facebook, Twitter & LinkedIn and make it easy to add more networks.
  3. Keep the HTML super simple so there are no problems with mobile browsers.
  4. Make sure the links are OK for SEO by using nofollow and/or noopener properly.

The final output will be a div element with some child links in it, like this:

<div class="share-to-socials">
	<a href="#" class="sharing">
		<svg>...</svg> <!-- the sharing icon -->
	</a>
	<a href="https://www.facebook.com/share.php?u=https://example.com/your-post" class="share-to-facebook">
		<svg>...</svg>
	</a>
	<a href="https://twitter.com/share?url=%s" class="share-to-twitter">
		<svg>...</svg>
	</a>
	<!--
	   More networks in here...
	-->
</div>

Every social media platform has a URL schema that allows quick sharing of external content to their network, although it can take some effort to find it in their documentation.

Scaffold the code

Start by going into your custom child theme and creating a file called “wpt-share-to-socials.php”, then paste the following into it:

<?php

/**
 * Headwall WP Tutorials Share to Socials : WPTSTS
 *
 * https://wp-tutorials.tech/refine-wordpress/add-share-to-social-links-to-wordpress-posts/
 *
 */
defined('WPINC') || die();

/**
 * The post types that will have the share-to-social links at the end. This
 * constant can be null, false, a string with a single post type, or an array of
 * post types.
 *
 * const WPTSTS_POST_TYPES_TO_SHARE = null;     // Disabled the social links completely
 * const WPTSTS_POST_TYPES_TO_SHARE = 'post';   // Only show on single posts
 * const WPTSTS_POST_TYPES_TO_SHARE = array('post', 'page', 'product');
 *
 */
const WPTSTS_POST_TYPES_TO_SHARE = 'post';

const WPTSTS_OPEN_IN_NEW_TAB = true;

/**
 * The list of networks we want to share to. Each of these needs a corresponding
 * filter-handler to create the link and icon HTML.
 *
 * If you add support for sharing to Yandex, add "yandex" to the WPTSTS_NETWORKS
 * array and create a filter handler called "get_share_to_yandex". Look at how
 * we implement the "facebook" network and use that as your template.
 *
 */
const WPTSTS_NETWORKS = array('facebook', 'twitter', 'linkedin', 'pinterest', 'clipboard');

/**
 * Simple SVGs to get started. You could swap these out for things like
 * '<i class="fab fa-facebook-square"></i>' if your site has Font Awesome
 * installed.
 */
const WPTSTS_SHARE_ICON = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Free 6.4.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. --><path d="M352 320c-22.608 0-43.387 7.819-59.79 20.895l-102.486-64.054a96.551 96.551 0 0 0 0-41.683l102.486-64.054C308.613 184.181 329.392 192 352 192c53.019 0 96-42.981 96-96S405.019 0 352 0s-96 42.981-96 96c0 7.158.79 14.13 2.276 20.841L155.79 180.895C139.387 167.819 118.608 160 96 160c-53.019 0-96 42.981-96 96s42.981 96 96 96c22.608 0 43.387-7.819 59.79-20.895l102.486 64.054A96.301 96.301 0 0 0 256 416c0 53.019 42.981 96 96 96s96-42.981 96-96-42.981-96-96-96z"/></svg>';
const WPTSTS_FACEBOOK_ICON = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!-- Font Awesome Pro 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) --><path d="M400 32H48A48 48 0 0 0 0 80v352a48 48 0 0 0 48 48h137.25V327.69h-63V256h63v-54.64c0-62.15 37-96.48 93.67-96.48 27.14 0 55.52 4.84 55.52 4.84v61h-31.27c-30.81 0-40.42 19.12-40.42 38.73V256h68.78l-11 71.69h-57.78V480H400a48 48 0 0 0 48-48V80a48 48 0 0 0-48-48z"/></svg>';
const WPTSTS_TWITTER_ICON = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!-- Font Awesome Pro 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) --><path d="M400 32H48C21.5 32 0 53.5 0 80v352c0 26.5 21.5 48 48 48h352c26.5 0 48-21.5 48-48V80c0-26.5-21.5-48-48-48zm-48.9 158.8c.2 2.8.2 5.7.2 8.5 0 86.7-66 186.6-186.6 186.6-37.2 0-71.7-10.8-100.7-29.4 5.3.6 10.4.8 15.8.8 30.7 0 58.9-10.4 81.4-28-28.8-.6-53-19.5-61.3-45.5 10.1 1.5 19.2 1.5 29.6-1.2-30-6.1-52.5-32.5-52.5-64.4v-.8c8.7 4.9 18.9 7.9 29.6 8.3a65.447 65.447 0 0 1-29.2-54.6c0-12.2 3.2-23.4 8.9-33.1 32.3 39.8 80.8 65.8 135.2 68.6-9.3-44.5 24-80.6 64-80.6 18.9 0 35.9 7.9 47.9 20.7 14.8-2.8 29-8.3 41.6-15.8-4.9 15.2-15.2 28-28.8 36.1 13.2-1.4 26-5.1 37.8-10.2-8.9 13.1-20.1 24.7-32.9 34z"/></svg>';
const WPTSTS_LINKEDIN_ICON = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!-- Font Awesome Pro 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) --><path d="M416 32H31.9C14.3 32 0 46.5 0 64.3v383.4C0 465.5 14.3 480 31.9 480H416c17.6 0 32-14.5 32-32.3V64.3c0-17.8-14.4-32.3-32-32.3zM135.4 416H69V202.2h66.5V416zm-33.2-243c-21.3 0-38.5-17.3-38.5-38.5S80.9 96 102.2 96c21.2 0 38.5 17.3 38.5 38.5 0 21.3-17.2 38.5-38.5 38.5zm282.1 243h-66.4V312c0-24.8-.5-56.7-34.5-56.7-34.6 0-39.9 27-39.9 54.9V416h-66.4V202.2h63.7v29.2h.9c8.9-16.8 30.6-34.5 62.9-34.5 67.2 0 79.7 44.3 79.7 101.9V416z"/></svg>';
const WPTSTS_PINTEREST_ICON = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Free 6.4.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. --><path d="M448 80v352c0 26.5-21.5 48-48 48H154.4c9.8-16.4 22.4-40 27.4-59.3 3-11.5 15.3-58.4 15.3-58.4 8 15.3 31.4 28.2 56.3 28.2 74.1 0 127.4-68.1 127.4-152.7 0-81.1-66.2-141.8-151.4-141.8-106 0-162.2 71.1-162.2 148.6 0 36 19.2 80.8 49.8 95.1 4.7 2.2 7.1 1.2 8.2-3.3.8-3.4 5-20.1 6.8-27.8.6-2.5.3-4.6-1.7-7-10.1-12.3-18.3-34.9-18.3-56 0-54.2 41-106.6 110.9-106.6 60.3 0 102.6 41.1 102.6 99.9 0 66.4-33.5 112.4-77.2 112.4-24.1 0-42.1-19.9-36.4-44.4 6.9-29.2 20.3-60.7 20.3-81.8 0-53-75.5-45.7-75.5 25 0 21.7 7.3 36.5 7.3 36.5-31.4 132.8-36.1 134.5-29.6 192.6l2.2.8H48c-26.5 0-48-21.5-48-48V80c0-26.5 21.5-48 48-48h352c26.5 0 48 21.5 48 48z"/></svg>';
const WPTSTS_COPY_ICON = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Free 6.4.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. --><path d="M326.612 185.391c59.747 59.809 58.927 155.698.36 214.59-.11.12-.24.25-.36.37l-67.2 67.2c-59.27 59.27-155.699 59.262-214.96 0-59.27-59.26-59.27-155.7 0-214.96l37.106-37.106c9.84-9.84 26.786-3.3 27.294 10.606.648 17.722 3.826 35.527 9.69 52.721 1.986 5.822.567 12.262-3.783 16.612l-13.087 13.087c-28.026 28.026-28.905 73.66-1.155 101.96 28.024 28.579 74.086 28.749 102.325.51l67.2-67.19c28.191-28.191 28.073-73.757 0-101.83-3.701-3.694-7.429-6.564-10.341-8.569a16.037 16.037 0 0 1-6.947-12.606c-.396-10.567 3.348-21.456 11.698-29.806l21.054-21.055c5.521-5.521 14.182-6.199 20.584-1.731a152.482 152.482 0 0 1 20.522 17.197zM467.547 44.449c-59.261-59.262-155.69-59.27-214.96 0l-67.2 67.2c-.12.12-.25.25-.36.37-58.566 58.892-59.387 154.781.36 214.59a152.454 152.454 0 0 0 20.521 17.196c6.402 4.468 15.064 3.789 20.584-1.731l21.054-21.055c8.35-8.35 12.094-19.239 11.698-29.806a16.037 16.037 0 0 0-6.947-12.606c-2.912-2.005-6.64-4.875-10.341-8.569-28.073-28.073-28.191-73.639 0-101.83l67.2-67.19c28.239-28.239 74.3-28.069 102.325.51 27.75 28.3 26.872 73.934-1.155 101.96l-13.087 13.087c-4.35 4.35-5.769 10.79-3.783 16.612 5.864 17.194 9.042 34.999 9.69 52.721.509 13.906 17.454 20.446 27.294 10.606l37.106-37.106c59.271-59.259 59.271-155.699.001-214.959z"/></svg>';


/**
 * Enqueue our styles.
 */
function wptsts_enqueue_scripts_and_styles() {
	if (wptsts_are_share_links_required()) {
		$theme_version = wp_get_theme()->get('Version');
		$base_uri = get_stylesheet_directory_uri();

		wp_enqueue_style(
			'wptsts',
			$base_uri . '/wpt-share-to-socials.css',
			null, // No style dependencies
			$theme_version
		);
	}
}
add_action('wp_enqueue_scripts', 'wptsts_enqueue_scripts_and_styles');

/**
 * If you want to dynamically change which social network sharing links are
 * visible, based on the content, you can use the "wptsts_networks" filter to
 * return a different array of networks.
 */
function wptsts_share_to_networks() {
	return (array) apply_filters('wptsts_networks', WPTSTS_NETWORKS);
}

/**
 * This lets us control which content should have the share-to-social links
 * enabled. This function is only triggered on singular content - not on archive
 * pages.
 */
function wptsts_are_share_links_required() {
	$are_required = false;

	if (is_admin() || wp_doing_ajax()) {
		// Do nothing
	} else {
		$current_post_type = get_post_type();

		if (empty(WPTSTS_POST_TYPES_TO_SHARE)) {
			// No post types are specified, so social sharing is effectively
			// disabled.
		} elseif (is_string(WPTSTS_POST_TYPES_TO_SHARE)) {
			$are_required = ($current_post_type == WPTSTS_POST_TYPES_TO_SHARE);
		} elseif (is_array(WPTSTS_POST_TYPES_TO_SHARE)) {
			$are_required = in_array($current_post_type, WPTSTS_POST_TYPES_TO_SHARE);
		} else {
			// WPTSTS_POST_TYPES_TO_SHARE is an unsupported type.
			error_log(__FUNCTION__ . ' : WPTSTS_POST_TYPES_TO_SHARE should be either null, false, a string or an array of strings');
		}
	}

	return $are_required;
}

/**
 * A utility function to get the current content's URL without any query args
 */
function wptsts_get_current_request_url() {
	global $wp;
	return home_url(add_query_arg(array(), $wp->request));
}

/**
 * Our core function that loops over the requires social networks and builds
 * the HTML.
 */
function wptsts_maybe_inject_share_links($content) {
	// TODO: Our core code will go in here...
	// ...

	return $content;
}
add_filter('the_content', 'wptsts_maybe_inject_share_links');

/**
 * Facebook filter handler.
 */
function wptsts_get_share_to_facebook($social_meta) {
	$social_meta['html'] = WPTSTS_FACEBOOK_ICON;
	$social_meta['href'] = sprintf(
		'https://www.facebook.com/share.php?u=%s',
		urlencode($social_meta['share_url'])
	);

	return $social_meta;
}
add_action('get_share_to_facebook', 'wptsts_get_share_to_facebook');

Next, create a file called “wpt-share-to-socials.css” and add the following to it:

/**
 * Headwall WP Tutorials Share to Socials : WPTSTS
 *
 * https://wp-tutorials.tech/refine-wordpress/add-share-to-social-links-to-wordpress-posts/
 *
 */

.share-to-socials {
	display: flex;
	gap: 1em;
	align-items: center;
	line-height: 1;
	flex-wrap: wrap;
}

.share-to-socials>* {
	min-width: 2em;
	min-height: 2em;
	display: block;
}

.share-to-socials .share-to-facebook i,
.share-to-socials .share-to-facebook svg path {
	fill: #4267B2;
}

.share-to-socials .share-to-twitter i,
.share-to-socials .share-to-twitter svg path {
	fill: #1DA1F2;
}

.share-to-socials .share-to-linkedin i,
.share-to-socials .share-to-linkedin svg path {
	fill: #0072b1;
}

.share-to-socials .share-to-pinterest i,
.share-to-socials .share-to-pinterest svg path {
	fill: #e60023;
}

/**
 * The copy-to-clipboard button
 */
.share-to-socials .share-to-clipboard {
	display: flex;
	align-items: center;
}

.share-to-socials .share-to-clipboard i,
.share-to-socials .share-to-clipboard svg path {
	fill: #333;
}

.share-to-socials .share-to-clipboard svg,
.share-to-socials .share-to-clipboard i {
	min-width: 1.5em;
	margin-right: 0.2em;
	padding: 0.2em;
}

.share-to-socials .share-to-clipboard span {
	white-space: nowrap;
}

Finally, open your child theme’s functions.php file and add the following couple of lines:

// WP Tutorials : Social share links
require_once dirname(__FILE__) . '/wpt-share-to-socials.php';

How the code works

The PHP code contains the following standard components:

  • At the top, we block direct access to the PHP file by verifying that WPINC has been defined by WordPress core.
  • We define the constants that control how our project will work.
  • wptsts_are_share_links_required() needs to return true on any singular (not archive) content that needs the social sharing links.
  • Hook the wp_enqueue_scripts action to add a reference to our CSS file in the header. We only include our CSS on content that needs it, by checking the output of wptsts_are_share_links_required().
  • wptsts_maybe_inject_share_links() is our core function that does the actual work. It hooks the the_content filter to modify the WordPress post content that gets rendered to the page. If wptsts_are_share_links_required() returns true, we just take the HTML that the_content has already created, and we append our HTML to the end of it.
  • Each social network is supported by a filter handler like “get_share_to_facebook” or “get_share_to_twitter”. These handlers should return an array that describes the share link.

Featured plugin

UK Gift Aid for WooCommerce
Accept charitable donations from anywhere on your WooCommerce site, including at the checkout. You can enable a UK Gift Aid consent for all products, or for specific products. You can also disable the UK Gift Aid option if you just need a robust donations plugin.
UK Gift Aid & Donations for WooCommerce

The Core function

Go back into wpt-share-to-socials.php and replace the contents of wptsts_maybe_inject_share_links() with the following:

function wptsts_maybe_inject_share_links($content) {
	if (is_admin() || wp_doing_ajax() || !in_the_loop() || !is_main_query()) {
		// ...
	} elseif (!wptsts_are_share_links_required()) {
		// Socials are not enabled here.
	} elseif (empty($networks = wptsts_share_to_networks())) {
		// No networks are specified.
	} elseif (empty($share_url = wptsts_get_current_request_url())) {
		// The current/share URL is empty. We should never end up in there.
		error_log(__FUNCTION__ . ' The current/share URL is empty. Weird.');
	} else {
		$sharing_html = '';

		foreach ($networks as $network) {
			// Create an array to describe the <a>...</a> element for our social
			// button. The filter needs to populate the "href" and "html" elements
			// for the link to get rendered.
			$social_meta = array(
				'attrs' => array(
					'title' => __('Share this post to', 'wp-tutorials') . ' ' . $network,
				),
				'share_url' => $share_url,
				'post_title' => get_the_title(),
				'href' => '', //  << The filter needs to populate this
				'html' => '', //  << The filter needs to populate this
				'classes' => array(
					'share-to-' . $network,
				),
			);

			if (WPTSTS_OPEN_IN_NEW_TAB) {
				$social_meta['attrs']['rel'] = 'nofollow noopener';
				$social_meta['attrs']['target'] = '_blank';
			} else {
				$social_meta['attrs']['rel'] = 'nofollow noreferrer';
			}

			// Trigger the social network filter to populate (or modify) elements
			// in our $social_meta array.
			$filter_name = 'get_share_to_' . $network;
			$social_meta = apply_filters($filter_name, $social_meta);

			// Only render the social link if the "html" and "href" elements have
			// been populated.
			if (!empty($social_meta['html']) && !empty($social_meta['href'])) {
				//  Open the "a" element.
				$sharing_html .= sprintf(
					'<a href="%s" class="%s"',
					esc_url($social_meta['href']),
					esc_attr(implode(' ', $social_meta['classes']))

				);

				// Loop through all the attributes and render them as
				// name="value" pairs.
				foreach ($social_meta['attrs'] as $attr_name => $attr_value) {
					$sharing_html .= sprintf(
						' %s="%s"',
						esc_attr($attr_name),
						esc_attr($attr_value)
					);

				}

				$sharing_html .= '>'; //  Close the "a" element.

				$sharing_html .= $social_meta['html'];

				$sharing_html .= '</a>';
			}
		}

		// Only render the share-to-socials if one or more links exist
		// (if there's something in $sharing_html).
		if (!empty($sharing_html)) {
			$content .= '<div class="share-to-socials">';

			// Add the "share" icon to the HTML first.
			$content .= sprintf(
				'<a href="#" title="%s" class="sharing">%s</a>',
				esc_attr__('Share to your socials', 'wp-tutorials'),
				WPTSTS_SHARE_ICON
			);

			// Add all the sharing icons
			$content .= $sharing_html;

			$content .= '</div>'; // .share-to-socials
		}
	}

	return $content;
}

The structure should be easy to follow, and it breaks down like this:

  • Fail if the execution conditions aren’t right
  • Log an error if the input parameters are invalid
  • Create an empty string to hold our HTML, $sharing_html
  • For each social network…
    • Get the $social_meta array for the share-to-social link
    • If $social_meta has “html” and “href” elements then…
      • Create the HTML for an <a>...</a> social link and append it to $sharing_html
  • If $sharing_html is not empty, then…
    • Append $sharing_html to the post’s content HTML
  • Return the post’s content HTML (which may or may not be modified)

Make sure everything is saved, then reload a single post on your site. You should see the Facebook social network icon at the end of your content 👍.

Adding more social networks

We’ve got “facebook”, “twitter”, “linkedin” and “pinterest” specified in WPTSTS_NETWORKS but we’ve only got a filter-handler for Facebook. So let’s add filter handlers for the other networks now. Go to the end of wpt-share-to-socials.php and append the following:

/**
 * Twitter filter handler.
 */
function wptsts_get_share_to_twitter($social_meta) {
	$social_meta['html'] = WPTSTS_TWITTER_ICON;
	$social_meta['href'] = sprintf(
		'https://twitter.com/share?url=%s&text=%s',
		urlencode($social_meta['share_url']),
		urlencode($social_meta['post_title'])
	);

	return $social_meta;
}
add_action('get_share_to_twitter', 'wptsts_get_share_to_twitter');

/**
 * LinkedIn filter handler.
 */
function wptsts_get_share_to_linkedin($social_meta) {
	$social_meta['html'] = WPTSTS_LINKEDIN_ICON;
	$social_meta['href'] = sprintf(
		'https://www.linkedin.com/sharing/share-offsite/?url=%s',
		urlencode($social_meta['share_url'])
	);

	return $social_meta;
}
add_action('get_share_to_linkedin', 'wptsts_get_share_to_linkedin');

/**
 * Pinterest filter handler.
 */
function wptsts_get_share_to_pinterest($social_meta) {
	$social_meta['html'] = WPTSTS_PINTEREST_ICON;
	$social_meta['href'] = sprintf(
		'https://pinterest.com/pin/create/link/?url=%s&description=%s',
		urlencode($social_meta['share_url']),
		urlencode($social_meta['post_title'])
	);

	return $social_meta;
}
add_action('get_share_to_pinterest', 'wptsts_get_share_to_pinterest');

There’s no rocket-science in there – each function just returns a modified version of its $social_meta array.

To add a completely new network, append the network’s name to the WPTSTS_NETWORKS array and then add a filter-handler for it. Use the Facebook network as an example.

Copy URL button

If you’ve added my JavaScript click-to-copy tutorial to your site, we can use it to add a “Copy link to the clipboard” button too. It works the same way as the other socials but we’re going to add slightly different HTML. We’ll also create an attribute called data-ctc="..." to hold the URL that needs to be copied.

Add this to the end of wpt-share-to-socials.php:

/**
 * Copy to clipboard.
 */
function wptsts_get_share_to_clipboard($social_meta) {
	// Only modify $social_meta if we know that the click-to-copy assets
	// are available and enqueued.
	if (function_exists('wptctc_is_required') && wptctc_is_required()) {
		$social_meta['html'] = sprintf(
			'%s<span>%s</span>',
			WPTSTS_COPY_ICON,
			'Copy'
		);

		// We need a dummy URL so the link will get rendered.
		$social_meta['href'] = 'javascript:void(0)';

		$social_meta['classes'][] = 'button';
		$social_meta['classes'][] = 'click-to-copy';

		$social_meta['attrs']['data-ctc'] = $social_meta['share_url'];
		$social_meta['attrs']['title'] = __('Copy URL to the clipboard', 'wp-tutorials');
	}

	return $social_meta;
}
add_action('get_share_to_clipboard', 'wptsts_get_share_to_clipboard');

That’s it. Happy socialising 😎 👍

Like This Tutorial?

Let us know

WordPress plugins for developers

3 thoughts on “Add Share-to-Social Links to WordPress Posts”

  1. Hey, I felt compelled to reach out and let you know how much I appreciated reading your website. Your ideas are genuinely amazing and have inspired me with a different outlook. I will be adding it to my own bookmarks and look forward to checking out your future posts. Thank you for putting in the time and keep up the fantastic job!

    Reply
  2. Great alternative to some of the plugins I found in the respository.
    The icons look really professional in my opinion.

    Am I correct the share icon used on this page is not included in the tutorial?
    Because without it, (mobile) site visitors might think that these are ‘follow-us on social’ icons, in stead of ‘share on social’ icons.

    Maybe the share icon, could even get a link that copy’s the current page URL to the clipboard.
    That might improve the user experience even further 🙂

    Reply
    • That’s a fair point.

      The “share” icon I use is injected via CSS (Font Awesome 5). I’ll look at replacing it with an inline SVG and including it in the tutorial 👍

      Reply

Leave a comment