Share buttons, in two lines of HTML.
Pick the services, copy the snippet, paste it where the buttons belong. No account, no dashboard, and no script sitting on your page watching who reads it.
In your snippet — 7 services
<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_whatsapp"></a> <a class="ats_btn_telegram"></a> <a class="ats_btn_email"></a> <a class="ats_btn_copy"></a> <a class="ats_dd"></a> </div> <script async src="//static.addtosite.com/widget.js"></script>
your page
An article worth passing on
Real buttons. Press one and the share window opens for this page.
79
services
20
icons inline
1
request
0
cookies
Here is every byte we receive.
One beacon, and only when a reader actually presses a button. Nothing on page view, nothing in a cookie, nothing that identifies anybody.
- No cookies, no identifierNo cookies, visitor identifiers or fingerprinting. Optional service preferences stay in the browser for the current site.
- No page-view trackingSharing sends an anonymous action ping. Optional count badges fetch aggregate totals; the widget does not send a page-view tracking event.
- Three fieldsService, page URL and a timestamp. The domain comes from the Origin header, never from the body.
- IPs are never storedThe address is hashed with a local salt on arrival and kept only long enough to ignore the same press twice inside a minute.
POST data.addtosite.com/v1/share
{
"network": "facebook",
"url": "https://yoursite.com/post",
"ts": 1789286400
}The domain is read from the Origin header, never the body. Turn the whole thing off with track: false.
Where are you pasting it?
All 12 guidesWordPress
Add the buttons under every post without touching a theme file twice.
Ends up
Under the content of every post, on self-hosted WordPress.
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.
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.
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; });
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.
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.
# 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.
{{ 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>
Joomla
A Custom HTML module puts the buttons under every article.
Ends up
In any template position, most usefully right after the article body.
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.
WordPress.com
Works on hosted WordPress even where custom scripts are blocked.
Ends up
Inside any post or page, through the editor.
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.
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.
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.
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); }, };
Ghost
Code injection loads the script; a theme edit places the buttons.
Ends up
Under the post content, on every post.
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.
<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.
{{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>
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.
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.
<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.
<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>
Webflow
An Embed element, plus one line in the project footer.
Ends up
Anywhere you can drop an element, including inside a Collection List.
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.
<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.
<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>
Blogger
Add the buttons to the post template, XML quirks and all.
Ends up
Under every post body, from the theme template.
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.
<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>
Tumblr
One theme edit puts the buttons under every post.
Ends up
Under each post in your theme.
{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.
<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>
Everything it does
Ten things, all of them switched on by a class or a single line of config. None of them ask for an account.
Share anywhere
79 destinations, plus any you add yourself. Each button opens the reader's app when they have it and the web when they do not.
Made for thumbs first
On a phone the menu fills the screen and the floating bar drops to the bottom edge. Tap targets stay comfortable at every button size.
Icons that stay sharp
Vectors drawn on a 24-pixel grid and inlined in the script: nothing to fetch, nothing to blur on a high-density screen, no icon host to be blocked.
Built to behave
Loaded async, labelled controls, real focus rings, Escape closes the menu. Your page renders first and the buttons catch up.
Analytics, no extra tag
If gtag or Tag Manager already runs on the page, every press arrives as a standard share event with the service and the URL. We add nothing of our own.
Nothing to sign up for
No registration, no key, no account to manage. Paste the two lines and the buttons work on the next page load.
Counts when you want them
One flag puts a badge on each button. A service nobody has shared yet shows nothing at all rather than a zero on launch day.
Floating share bars
A bar that follows the reader down the page — pinned left, pinned right, or laid across the bottom once the screen gets narrow.
A guide per platform
12 platforms, each with the exact file to open, the snippet to paste and the one thing that usually bites.
Customizable to the edge
Override a brand colour, swap one service's endpoint, add a destination the catalog has never heard of, or point counting at a backend you run.
Add it once.
Forget it forever.
No account, no dashboard, no script watching your readers. Two lines of HTML and the buttons are somebody else’s problem.