Membership CTA Web Component
<simply-club-membership-cta> is a self-contained web component that renders the SimplyClub membership call-to-action. Drop it into any page โ Shopify, WordPress, custom HTML โ and it renders the join/upgrade CTA, handles its own styling, and emits events you can react to.
Install
Load the module once per page. The custom element registers itself automatically.
<script type="module">
import "https://dropins.simplyclub.co.il/drop-ins/membership-cta-web-component/index.mjs";
</script>
The import is a side-effect โ there is nothing to assign to a variable. Loading the module is what defines the
<simply-club-membership-cta>tag.
Use
Place the element where you want the CTA to appear:
<simply-club-membership-cta></simply-club-membership-cta>
Optional inline styling for layout:
<simply-club-membership-cta
style="display:block; width:95%; margin:36px auto 25px;">
</simply-club-membership-cta>
The component renders its own internal UI and brand styling โ you only need to control its placement and outer dimensions.
Events
The component dispatches custom events on the document that your page can listen to.
| Event | When it fires | Detail |
|---|---|---|
simply-club:login |
The user clicks the CTA while not logged in | โ |
Example โ open your existing login dialog when SimplyClub asks for login:
<script>
document.addEventListener('simply-club:login', () => {
const dialog = document.querySelector("[ref='dialog'][open]");
dialog?.click();
});
</script>
Platform recipes
The component is platform-agnostic โ wherever you can put HTML and a <script> tag, you can put the CTA. The recipes below show the most common integrations.
Generic HTML / custom site
Drop the import once (near the end of <body> or in <head>), then place the element where you want the CTA. This is the simplest case โ no observers, no extra logic.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>My store</title>
<script type="module">
import "https://dropins.simplyclub.co.il/drop-ins/membership-cta-web-component/index.mjs";
</script>
</head>
<body>
<main>
<h1>Welcome</h1>
<!-- The CTA lives anywhere in your layout -->
<simply-club-membership-cta
style="display:block; max-width:480px; margin:32px auto;">
</simply-club-membership-cta>
<p>Rest of the pageโฆ</p>
</main>
<script>
// Open your existing login modal when the CTA asks for login.
document.addEventListener('simply-club:login', () => {
document.getElementById('my-login-modal')?.showModal?.();
});
</script>
</body>
</html>
WordPress (theme footer or header/footer plugin)
Add the script + element via a header/footer injection plugin (e.g. Insert Headers and Footers, WPCode), or by editing your theme's footer.php. Both achieve the same outcome โ the plugin approach survives theme updates.
<!-- Paste into the FOOTER section of your header/footer plugin, or before </body> in footer.php -->
<script type="module">
import "https://dropins.simplyclub.co.il/drop-ins/membership-cta-web-component/index.mjs";
</script>
<script>
document.addEventListener('simply-club:login', () => {
// Redirect to the WordPress login (replace with a modal if you prefer)
window.location.href = '/wp-login.php';
});
</script>
Then add the element wherever you want the CTA to appear:
- In a page or post โ paste the markup into the block editor as a Custom HTML block:
<simply-club-membership-cta style="display:block; max-width:480px; margin:32px auto;"></simply-club-membership-cta> - In a sidebar or footer โ use a Custom HTML widget with the same markup.
- In a template part โ drop the markup directly into
header.php,single.php,page.php, etc.
Block-editor tip: if WordPress strips custom elements from the post HTML, switch to a Custom HTML block instead of a paragraph block. Custom HTML blocks preserve the element verbatim.
WooCommerce (mini-cart, checkout, my-account)
WooCommerce often re-renders the mini-cart asynchronously after AJAX add-to-cart events. Use a MutationObserver to mount the CTA whenever the mini-cart appears:
<script type="module">
import "https://dropins.simplyclub.co.il/drop-ins/membership-cta-web-component/index.mjs";
</script>
<script>
(function () {
function insertCTA() {
const target = document.querySelector('.woocommerce-mini-cart, .widget_shopping_cart_content');
if (!target) return;
if (target.querySelector('simply-club-membership-cta')) return;
const cta = document.createElement('simply-club-membership-cta');
cta.style.cssText = 'display:block; width:95%; margin:20px auto;';
target.prepend(cta);
}
document.addEventListener('simply-club:login', () => {
window.location.href = '/my-account/';
});
new MutationObserver(insertCTA).observe(document.body, { childList: true, subtree: true });
insertCTA(); // also try once on initial load
})();
</script>
For checkout and my-account pages, use static placement (a shortcode, a template part, or a Custom HTML block) instead โ those pages aren't re-rendered, so an observer is unnecessary overhead.
Shopify (cart drawer)
Shopify's cart drawer is created only after the user opens the cart, so the CTA needs to be mounted dynamically. Use the same MutationObserver pattern with Shopify's cart-drawer selectors:
<script type="module">
import "https://dropins.simplyclub.co.il/drop-ins/membership-cta-web-component/index.mjs";
</script>
<script>
(function () {
function insertCTA() {
const header = document.querySelector('.cart-drawer__header');
if (!header) return;
if (document.querySelector('simply-club-membership-cta')) return;
const cta = document.createElement('simply-club-membership-cta');
cta.style.display = 'block';
cta.style.width = '95%';
cta.style.margin = '36px auto 25px';
header.insertAdjacentElement('afterend', cta);
}
document.addEventListener('simply-club:login', () => {
const dialog = document.querySelector("[ref='dialog'][open]");
dialog?.click();
});
new MutationObserver(insertCTA).observe(document.body, { childList: true, subtree: true });
})();
</script>
The selector (.cart-drawer__header) is theme-specific โ inspect the drawer in DevTools and adjust if your theme uses different class names.
Static vs. dynamic placement โ which to choose
| Where you want the CTA | Strategy |
|---|---|
| Inline in a page, post, sidebar, or footer | Static โ place the <simply-club-membership-cta> element directly in HTML. |
| Inside a drawer, modal, or section that mounts on user interaction | Dynamic โ MutationObserver watches for the container, then inserts the CTA once. |
| Inside a region re-rendered by AJAX (WooCommerce mini-cart, Shopify cart drawer) | Dynamic with duplicate guard โ re-runs every DOM change, but checks for an existing CTA before inserting. |
The duplicate-guard (if (target.querySelector('simply-club-membership-cta')) return;) is the critical piece for any dynamic mount โ without it, repeated DOM mutations will stack multiple CTAs on top of each other.
Tips
- Load the script once. Multiple imports are deduplicated by the browser, but you only need it in one place โ ideally in
<head>or near the top of<body>. - Sizing. The component renders block-level. Constrain it with
width,max-width, andmarginon the element itself. - Guard against duplicates. When inserting dynamically, always check for an existing
simply-club-membership-ctabefore creating a new one. Cart drawers can re-render multiple times per session. - Don't wrap in display:none. The component initializes when it is connected to the DOM. Hiding it via
display:nonecan prevent its internal logic from running.
Troubleshooting
<simply-club-membership-cta>renders as empty / unknown element โ the module import failed or hasn't run yet. Confirm the<script type="module">tag is present and the import URL is reachable from the storefront.- CTA does not appear in the cart drawer โ your theme's drawer header selector is different. Inspect the drawer in DevTools and update the selector in
insertCTA. simply-club:loginfires but nothing happens โ the dialog selector[ref='dialog'][open]is theme-specific. Replace it with whatever opens your store's login modal.- CTA appears multiple times โ the duplicate-guard
querySelector('simply-club-membership-cta')is missing or your insertion logic creates a CTA before the guard runs.