Platform guides
Share buttons for WordPress, Shopify and more
WordPress
Add the buttons under every post without touching a theme file twice.
Ends up
Under the content of every post, on self-hosted WordPress.
What bites
Editing the parent theme loses your work
Anything added through Appearance → Theme File Editor on a parent theme is overwritten by the next theme update. Use a child theme, or a code-snippets plugin, and the buttons survive.
01 Load the script once, site-wide
Appearance → Theme File Editor, or better, a child theme. Add this to functions.php so the script loads on every page rather than being pasted into each post.
php
add_action('wp_enqueue_scripts', function () { wp_enqueue_script( 'addtosite', '//static.addtosite.com/widget.js', array(), null, true ); });02 Append the buttons to every post
Still in functions.php. Filtering the_content puts the buttons under the post body wherever your theme renders it, so a theme update cannot lose them.
php
add_filter('the_content', function ($content) { if (!is_singular('post') || !in_the_loop() || !is_main_query()) { return $content; } $kit = '<div class="ats_kit ats_kit_size_32"' . ' data-url="' . esc_url(get_permalink()) . '"' . ' data-title="' . esc_attr(get_the_title()) . '">' . '<a class="ats_btn_facebook"></a>' . '<a class="ats_btn_x"></a>' . '<a class="ats_btn_linkedin"></a>' . '<a class="ats_btn_email"></a>' . '<a class="ats_dd"></a>' . '</div>'; return $content . $kit; });03 Or drop it into one post by hand
In the block editor, add a Custom HTML block where you want the buttons and paste the snippet the configurator gives you. Good for trying it out before committing to the filter.
Drupal
Add the buttons to any content type through a block or a Twig template.
Ends up
Below the body field of whichever content types you choose.
What bites
Restricted HTML strips the markup
Drupal text formats filter HTML. A custom block saved as Basic HTML will lose the empty anchors and the data attributes. Set the format to Full HTML, or the buttons render as nothing at all.
01 Load the script from your theme
Declare it as a library in THEME.libraries.yml, then attach it in THEME.info.yml so it loads on every page.
yaml
# THEME.libraries.yml addtosite: js: //static.addtosite.com/widget.js: { type: external, attributes: { async: true } } # THEME.info.yml libraries: - THEME/addtosite02 Put the buttons in the node template
Copy node.html.twig into your theme and add the kit after the content. Twig gives you the canonical URL and title, so each node shares itself rather than the front page.
twig
{{ content }} <div class="ats_kit ats_kit_size_32" data-url="{{ url('entity.node.canonical', {'node': node.id}) }}" data-title="{{ label|render|striptags|trim }}"> <a class="ats_btn_facebook"></a> <a class="ats_btn_x"></a> <a class="ats_btn_linkedin"></a> <a class="ats_btn_email"></a> <a class="ats_dd"></a> </div>03 Or use a block, with no theme edit at all
Structure → Block layout → Add custom block, set the text format to Full HTML, paste the snippet, then place the block in the Content region and limit it to the content types you want.
Joomla
A Custom HTML module puts the buttons under every article.
Ends up
In any template position, most usefully right after the article body.
What bites
The editor eats empty tags
TinyMCE removes empty anchors when it saves, which deletes every button. Switch the editor to Code / None before pasting, or set Editor to "None" in your user profile while you work.
01 Create a Custom HTML module
Content → Site Modules → New → Custom. Switch the editor to code view before pasting, then paste the snippet from the configurator.
02 Place it where articles end
Set Position to a slot your template renders below the article — most templates offer one. On the Menu Assignment tab choose On all pages, or just the menu items you want.
03 Load the script once
Rather than putting the script tag in the module, add it to your template index.php so it loads once per page instead of once per module.
php
<?php $doc = JFactory::getDocument(); $doc->addScript('//static.addtosite.com/widget.js', [], ['async' => true]);
WordPress.com
Works on hosted WordPress even where custom scripts are blocked.
Ends up
Inside any post or page, through the editor.
What bites
It fails quietly, not loudly
A stripped script leaves no error and no gap on the page — the markup is simply gone when you reload. If the buttons vanished after saving, that is what happened; switch to the plain-links build.
01 Check which plan you are on
WordPress.com only runs custom JavaScript on the Business plan and above. On Free, Personal and Premium the script tag is stripped silently — the buttons simply never appear. The rest of this page covers both cases.
02 Business plan: paste the normal snippet
Add a Custom HTML block where the buttons belong and paste what the configurator gives you. Everything works: the More menu, the counters, the floating bar.
03 Any other plan: use plain links
Open the configurator, tick "Plain links, no JavaScript", and fill in the page URL. That build is nothing but anchors around images, so nothing gets stripped. You lose the More menu and the share counts; the buttons themselves work everywhere.
Cloudflare
Inject the buttons at the edge, with no change to your origin at all.
Ends up
Into the HTML of every response, rewritten as it passes through Cloudflare.
What bites
Cached HTML keeps the old markup
If Cloudflare is caching your HTML, pages already in the cache will not have the buttons. Purge the cache after deploying the Snippet, or you will spend an hour debugging a rule that already works.
01 Create a Snippet
In the dashboard: Rules → Snippets → Create. Snippets run on the edge and can rewrite HTML without your origin server knowing anything about it.
02 Rewrite the HTML on its way through
HTMLRewriter streams the response, so this adds no meaningful latency and never buffers the page.
javascript
export default { async fetch(request) { const response = await fetch(request); // Only rewrite HTML; images and JSON pass straight through. if (!response.headers.get('content-type')?.includes('text/html')) { return response; } return new HTMLRewriter() .on('article', { element(el) { el.append( '<div class="ats_kit ats_kit_size_32">' + '<a class="ats_btn_facebook"></a>' + '<a class="ats_btn_x"></a>' + '<a class="ats_dd"></a>' + '</div>', { html: true } ); }, }) .on('body', { element(el) { el.append('<script async src="//static.addtosite.com/widget.js"></' + 'script>', { html: true }); }, }) .transform(response); }, };03 Limit it to the pages that need it
Give the Snippet a rule like `http.request.uri.path matches "^/blog/"` so it never touches your checkout, your admin, or your API.
Ghost
Code injection loads the script; a theme edit places the buttons.
Ends up
Under the post content, on every post.
What bites
Leave out absolute="true" and every post shares the same link
{{url}} on its own renders a relative path. The widget then falls back to the current page URL, which looks right on a post page and wrong everywhere else.
01 Load the script from Code injection
Settings → Code injection → Site footer. This survives theme changes, which is what makes it the right place for it.
html
<script async src="//static.addtosite.com/widget.js"></script>
02 Place the buttons in the post template
Edit post.hbs in your theme and add the kit after {{content}}. Handlebars gives you the absolute URL, so posts share themselves rather than whatever page the reader happens to be on.
handlebars
{{content}} <div class="ats_kit ats_kit_size_32" data-url="{{url absolute="true"}}" data-title="{{title}}"> <a class="ats_btn_facebook"></a> <a class="ats_btn_x"></a> <a class="ats_btn_linkedin"></a> <a class="ats_btn_email"></a> <a class="ats_dd"></a> </div>03 No theme access? Use an HTML card
In the editor, add an HTML card at the end of a post and paste the snippet. Per-post rather than automatic, but it needs no theme upload.
Shopify
Share buttons on product pages, with the product URL filled in by Liquid.
Ends up
On the product page, under the description or beside the buy button.
What bites
product.url is relative
Liquid renders {{ product.url }} as /products/thing, with no domain. Sharing that gives everyone a broken link, so prefix it with {{ shop.url }} as above. Pinterest deserves a place in the list here — it is where product images actually travel.
01 Load the script from the layout
Online Store → Themes → Edit code → layout/theme.liquid. Put it just before </body> so it never blocks the storefront rendering.
liquid
<script async src="//static.addtosite.com/widget.js"></script>
02 Add the buttons to the product template
Edit sections/main-product.liquid and place the kit where it belongs in the product layout. Liquid supplies the canonical product URL and title.
liquid
<div class="ats_kit ats_kit_size_32" data-url="{{ shop.url }}{{ product.url }}" data-title="{{ product.title | escape }}"> <a class="ats_btn_facebook"></a> <a class="ats_btn_pinterest"></a> <a class="ats_btn_whatsapp"></a> <a class="ats_btn_email"></a> <a class="ats_dd"></a> </div>03 Blog posts too
The same kit goes in sections/main-article.liquid, with data-url="{{ shop.url }}{{ article.url }}" and data-title="{{ article.title | escape }}".
Webflow
An Embed element, plus one line in the project footer.
Ends up
Anywhere you can drop an element, including inside a Collection List.
What bites
The Designer canvas shows nothing
Embeds do not run scripts inside the Designer, so the buttons look like an empty box while you are editing. Publish, or use the preview, before concluding it is broken.
01 Load the script once
Project Settings → Custom Code → Footer Code. Loading it here rather than inside each embed means one request no matter how many kits the page has.
html
<script async src="//static.addtosite.com/widget.js"></script>
02 Drop in an Embed element
Add an Embed where the buttons belong and paste the markup. Leave the script out of the embed — the footer already loaded it.
html
<div class="ats_kit ats_kit_size_32"> <a class="ats_btn_facebook"></a> <a class="ats_btn_x"></a> <a class="ats_btn_linkedin"></a> <a class="ats_btn_email"></a> <a class="ats_dd"></a> </div>
03 Inside a Collection List, bind the URL
Webflow lets an Embed take field values. Use them for data-url so each item in the list shares its own page rather than the list page.
html
<div class="ats_kit ats_kit_size_32" data-url="https://yoursite.com/blog/{{ slug }}" data-title="{{ name }}"> <a class="ats_btn_facebook"></a> <a class="ats_dd"></a> </div>
Blogger
Add the buttons to the post template, XML quirks and all.
Ends up
Under every post body, from the theme template.
What bites
Blogger themes are XML, not HTML
Unclosed tags and bare & characters make the theme refuse to save, usually with an unhelpful line number. Close every tag as above, write & for &, and use single quotes for attributes as Blogger does throughout.
01 Open the theme HTML
Theme → the arrow beside Customize → Edit HTML. Take a backup first: Theme → Backup. Blogger gives you no undo.
02 Find the post body and add the kit after it
Search for data:post.body. Blogger themes are XML, so every tag must be closed and Blogger expressions supply the URL and title.
xml
<data:post.body/> <div class='ats_kit ats_kit_size_32' expr:data-url='data:post.url' expr:data-title='data:post.title'> <a class='ats_btn_facebook'/> <a class='ats_btn_x'/> <a class='ats_btn_email'/> <a class='ats_dd'/> </div>03 Load the script before </body>
Still in the template. The tag has to be closed the XML way or the theme will not save.
xml
<script async='async' src='//static.addtosite.com/widget.js'/>
Tumblr
One theme edit puts the buttons under every post.
Ends up
Under each post in your theme.
What bites
{PlaintextTitle} is empty on photo and quote posts
Not every Tumblr post type has a title. The widget falls back to the page title when data-title is empty, so nothing breaks — but if you want something better, wrap the attribute in {block:Title}.
01 Edit the theme HTML
Blog settings → Edit theme → Edit HTML. Copy the whole thing somewhere safe first; Tumblr has no version history for themes.
02 Add the kit inside the post block
Find {block:Posts} and place the kit before {/block:Posts}. Tumblr fills in the permalink and title per post.
html
<div class="ats_kit ats_kit_size_32" data-url="{Permalink}" data-title="{PlaintextTitle}"> <a class="ats_btn_facebook"></a> <a class="ats_btn_x"></a> <a class="ats_btn_email"></a> <a class="ats_dd"></a> </div>03 Load the script before </body>
Near the bottom of the same template.
html
<script async src="//static.addtosite.com/widget.js"></script>