๐Ÿšง
Work in progress
We're still writing this guide โ€” details may change as it's finalized.
Web Components Web Shopify WordPress

Membership CTA Web Component

Embed the SimplyClub membership call-to-action anywhere on your site using a single custom element.


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, and margin on the element itself.
  • Guard against duplicates. When inserting dynamically, always check for an existing simply-club-membership-cta before 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:none can 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:login fires 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.