Share buttons for Facebook, X and LinkedIn usually come with a plugin that loads its own scripts and tracking on every page. When all you need are three links under each post, or on every card in a post grid, a WordPress shortcode is enough.
This post started as a shortcode for social share buttons in an Oxygen repeater. The rewritten [social_media] shortcode still works there, and also in post content, a Shortcode block in a block theme template, a Query Loop and other page builder repeaters. In a loop, each card shares its own post.
The snippet
<?php
/**
* [social_media] share buttons (Facebook, X, LinkedIn) for the current post.
* Usage: [social_media], [social_media networks="x,linkedin"], [social_media id="42"]
* Works in post content, a Shortcode block, Query Loops and page builder repeaters.
*/
function dpc_social_share_networks(): array {
return array(
'facebook' => array(
'label' => 'Facebook',
'url' => 'https://www.facebook.com/sharer/sharer.php?u={url}',
'viewbox' => '0 0 24 28',
'path' => 'M19.5 2c2.484 0 4.5 2.016 4.5 4.5v15c0 2.484-2.016 4.5-4.5 4.5h-2.938v-9.297h3.109l0.469-3.625h-3.578v-2.312c0-1.047 0.281-1.75 1.797-1.75l1.906-0.016v-3.234c-0.328-0.047-1.469-0.141-2.781-0.141-2.766 0-4.672 1.687-4.672 4.781v2.672h-3.125v3.625h3.125v9.297h-8.313c-2.484 0-4.5-2.016-4.5-4.5v-15c0-2.484 2.016-4.5 4.5-4.5h15z',
),
'x' => array(
'label' => 'X',
'url' => 'https://x.com/intent/tweet?url={url}&text={title}',
'viewbox' => '0 0 24 24',
'path' => 'M18.901 1.153h3.68l-8.04 9.19L24 22.846h-7.406l-5.8-7.584-6.638 7.584H.474l8.6-9.83L0 1.154h7.594l5.243 6.932ZM17.61 20.644h2.039L6.486 3.24H4.298Z',
),
'linkedin' => array(
'label' => 'LinkedIn',
'url' => 'https://www.linkedin.com/sharing/share-offsite/?url={url}',
'viewbox' => '0 0 24 28',
'path' => 'M3.703 22.094h3.609v-10.844h-3.609v10.844zM7.547 7.906c-0.016-1.062-0.781-1.875-2.016-1.875s-2.047 0.812-2.047 1.875c0 1.031 0.781 1.875 2 1.875h0.016c1.266 0 2.047-0.844 2.047-1.875zM16.688 22.094h3.609v-6.219c0-3.328-1.781-4.875-4.156-4.875-1.937 0-2.797 1.078-3.266 1.828h0.031v-1.578h-3.609s0.047 1.016 0 10.844v0h3.609v-6.062c0-0.313 0.016-0.641 0.109-0.875 0.266-0.641 0.859-1.313 1.859-1.313 1.297 0 1.813 0.984 1.813 2.453v5.797zM24 6.5v15c0 2.484-2.016 4.5-4.5 4.5h-15c-2.484 0-4.5-2.016-4.5-4.5v-15c0-2.484 2.016-4.5 4.5-4.5h15c2.484 0 4.5 2.016 4.5 4.5z',
),
);
}
add_shortcode( 'social_media', 'dpc_social_share_shortcode' );
function dpc_social_share_shortcode( $atts ): string {
$atts = shortcode_atts(
array(
'networks' => 'facebook,x,linkedin',
'id' => 0,
),
$atts,
'social_media'
);
$post = absint( $atts['id'] ) ? get_post( absint( $atts['id'] ) ) : get_post();
if ( ! $post || ! is_post_publicly_viewable( $post ) ) {
return '';
}
$url = rawurlencode( get_permalink( $post ) );
$title = rawurlencode( html_entity_decode( wp_strip_all_tags( get_the_title( $post ) ), ENT_QUOTES, get_bloginfo( 'charset' ) ) );
$all = dpc_social_share_networks();
$links = '';
foreach ( array_map( 'trim', explode( ',', strtolower( (string) $atts['networks'] ) ) ) as $key ) {
if ( ! isset( $all[ $key ] ) ) {
continue;
}
$network = $all[ $key ];
$links .= sprintf(
'<a class="dpc-share__link dpc-share__link--%1$s" href="%2$s" target="_blank" rel="noopener noreferrer" aria-label="%3$s"><svg viewBox="%4$s" width="32" height="32" aria-hidden="true" focusable="false"><path d="%5$s"/></svg></a>',
esc_attr( $key ),
esc_url( str_replace( array( '{url}', '{title}' ), array( $url, $title ), $network['url'] ) ),
/* translators: %s: network name, e.g. Facebook. */
esc_attr( sprintf( __( 'Share on %s', 'dpc' ), $network['label'] ) ),
esc_attr( $network['viewbox'] ),
esc_attr( $network['path'] )
);
}
if ( '' === $links ) {
return '';
}
dpc_social_share_style();
return '<div class="dpc-share">' . $links . '</div>';
}
/** The small stylesheet, once per page and only on pages that show the buttons. */
function dpc_social_share_style(): void {
if ( wp_style_is( 'dpc-share', 'enqueued' ) ) {
return;
}
wp_register_style( 'dpc-share', false, array(), '1.0' );
wp_add_inline_style(
'dpc-share',
'.dpc-share{display:flex;flex-direction:row;flex-wrap:wrap;gap:8px}'
. '.dpc-share__link{display:inline-flex;color:inherit;line-height:0}'
. '.dpc-share__link svg{width:32px;height:32px;fill:currentColor}'
. '.dpc-share__link:hover,.dpc-share__link:focus-visible{opacity:.75}'
);
wp_enqueue_style( 'dpc-share' );
}
Use it
[social_media]shows all three buttons for the current post.[social_media networks="x,linkedin"]picks networks and their order. Unknown names are ignored.[social_media id="42"]shares another post, for example on a landing page.- In Oxygen, add a Shortcode element inside the Repeater and enter
[social_media]. In a block theme, add a Shortcode block inside the Query Loop’s Post Template.
How it works
- The permalink and title are encoded with
rawurlencode()and every attribute is escaped, so titles with&or quotes cannot break the links. - X uses
x.com/intent/tweetand LinkedIn the currentshare-offsiteURL. The oldtwitter.com/home?status=link from the first version no longer opens a share dialog. - Links open in a new tab with
rel="noopener noreferrer", have an accessible name such as “Share on Facebook”, and the icons are hidden from screen readers. - The first version gave every icon the same
id, so a repeater with ten posts had thirty duplicate IDs, and printed a<style>tag for every item. Now there are only classes, and a small stylesheet is added once per page, only on pages that show buttons. - Drafts and private posts print nothing, so you never share a link that visitors cannot open.
Add it with Scripts Organizer
In Scripts Organizer go to Code Blocks → Add New and give the block a name. Set Trigger location to Everywhere, tick PHP under Script location, paste the code into the PHP editor and publish. Leave Action/Hook empty.
Everywhere registers the shortcode on every request, including the builder and block editor previews. The CSS lives inside the PHP on purpose: Scripts Organizer prints Header and Footer code only with the Conditions trigger, and the shortcode adds its styles itself where it is used.
The same code also works unchanged in a small plugin or an mu-plugin.
Customise it
- Another network: add an entry to
dpc_social_share_networks()with a share URL using{url}and{title}, and an SVG path. For example WhatsApp withhttps://wa.me/?text={title}%20{url}. - Brand colours: add rules such as
.dpc-share__link--facebook{color:#1877f2}to the inline CSS. - Size: change
32pxin the CSS.
Gotchas
- Networks read the page’s Open Graph tags for the preview image and text. Without an SEO plugin that prints them, the preview may be plain.
- If another plugin also registers
[social_media], the one loaded last wins. Rename the tag inadd_shortcode()andshortcode_atts().
In the Scripts Organizer library Import it with one click from Scripts Organizer.