Vanilla JS Guide

Article author
Memberstack Team

Introduction

Memberstack can be integrated into a Vanilla JS environment in two distinct ways:

  1. Utilizing the @memberstack/dom NPM package.
  2. Employing the memberstack.js static library.

Comparing the Two Methods

  • @memberstack/dom NPM Package: This is our core API, also used for our Webflow & React integrations. Installation requires a Node development server, build tools, and a package manager.
  • memberstack.js Static Library: This is identical to the script used in Webflow, allowing you to utilize our ms-member data-attribute directives. This method does not require build tools, package managers, or a Node development server.

When to Use each Method

  • Opt for @memberstack/dom if:
    • You're building a Single Page App (SPA).
    • Your project incorporates node package managers & build tools.
    • You're using frameworks that need compilation & build steps, like Vue SFCs, SvelteKit, or Typescript.
  • Choose memberstack.js for:
    • Ease of use with ms-member data-attribute directives.
    • Projects without package managers or build steps.
    • Simplicity in integration, especially with non-SPA websites.

Key Considerations for memberstack.js:

  • This script doesn’t reinitialize in SPAs with virtual DOMs.
  • Auth-related data attributes on forms will redirect users based on your dashboard settings in Memberstack.
  • A test mode banner appears if production/live domains aren't configured in the dashboard.

Quick Start

Using Memberstack From a Static Script

If you prefer working without the added complexity of build tools and package managers, or you want to opt-in to our special memberstack data-attribute directives, you can use memberstack.js directly with a script tag:

<script
  data-memberstack-app="app_..." // your project's APP ID
  src="<https://static.memberstack.com/scripts/v1/memberstack.js>"
  type="text/javascript"
>
</script>

In addition to using our data attributes, you can now access all of the core methods available in our DOM API using the $memberstackDom global variable exposed in the window. You can also override the default amount of days that a session persists.

<html lang="en">
  <head>
    <script
      data-memberstack-app="app_cl92vfop300wr0vjm2q3n4njb"
      src="<https://static.memberstack.com/scripts/v1/memberstack.js>"
      type="text/javascript"
    ></script>
  </head>
  <body>  
    <script> 
      const memberstack = window.$memberstackDom;
      // Session Duration
      ms_session_duration_days = 14 //days
      memberstack.getApp().then(({ data : app }) => console.log({ app }))
    </script>
  </body>
</html>

Installing the DOM package

If you prefer working with frameworks, build tools and package managers, you can install Memberstack DOM from the NPM public registry, or yarn.

Run the following command in your terminal:

npm install @memberstack/dom
#or
yarn add @memberstack/dom

After the package has been installed successfully, you can initialize the Memberstack instance by supplying your public key (found in the dev tools section of the dashboard).

import memberstackDOM from "@memberstack/dom";

const memberstack = memberstackDOM.init({
  publicKey: "pk_...",
});

Besides passing the default initialization object values, the DOM package also allows you to pass a sessionDurationDays field. This allows you to override the default amount of days that a session persists.

import memberstackDOM from "@memberstack/dom";

const memberstack = memberstackDOM.init({
  publicKey: "pk_...",
  sessionDurationDays: 7
});

Authentication

  • Signup Examples (without paid plans)
    • Static Signup Example w/ Data Attributes (no JavaScript)

      Using a classic form:

      <!-- memberstack.js script must be installed in <head /> -->
      <body>
        <main>
          <h1>Sign Up</h1>
          <br />
          <form data-ms-form="signup">
            <input name="email" type="text" data-ms-member="email" />
            <input name="password" type="text" data-ms-member="password" />
          </form>
        </main>
      </body>
      

      Using our pre-built UI modals:

      <!-- memberstack.js script must be installed in <head /> -->
      <body>
        <nav>
          <button data-ms-modal="signup">Sign Up</button>
        </nav>
      ...
      
    • Static Signup Example w/ raw JavaScript methods

      <!-- memberstack.js script must be installed in <head /> -->
      <body>
        <main>
          <h1>Sign Up</h1>
          <br />
          <form id="signup-form">
            <input name="email" type="text" />
            <input name="password" type="text" />
            <button type="submit">Sign Up</button>
          </form>
        </main>
        <script>
          const memberstack = window.$memberstackDom;
          const redirectTo = (path) => { window.location.href = path }
      		
          const signupMember => ({ email, password }) =>
          memberstack
          .signupMemberEmailPassword({ email, password })
          .then(({ data: member }) => { redirectTo("/onboarding") })
      
          const handleSubmit = (e) => {
            e.preventDefault();
            let email = e.target.email.value
            let password = e.target.password.value
            signupMember({ email, password })
           }
      	
           // listen for form submissions
           document.getElementById('signup-form')
           .addEventListener('submit', handleSubmit);
        </script>
      </body>
      

      Using our pre-built UI modals:

      <!-- memberstack.js script must be installed in <head /> -->
      <body>
        <main>
          <h1>Sign Up</h1>
          <br />
          <button id="signup">Sign Up</button>
        </main>
        <script>
          const memberstack = window.$memberstackDom;
          const signupButton = document.getElementById('signup');
      
          const redirectTo = (path) => { window.location.href = path }
      
          signupButton.addEventListener('click', () => {
            memberstack.openModal('SIGNUP').then(({ data }) => {
              memberstack.hideModal();
              redirectTo('/onboarding')
            });
          });
      		
        </script>
      </body>
      
    • Signup Example w/ @memberstack/dom

      You can utilize the same code shown in the raw JavaScript method section above. The only difference is that instead of using the memberstack.js script tag, you’d import the library at the top of your file.

      With modular apps, the best practice is typically creating a reusable memberstack instance that you can import in multiple files.

      // lib/memberstack.js
      
      import memberstackDOM from "@memberstack/dom";
      
      const memberstack = memberstackDOM.init({
        publicKey: "pk_...",
      });
      
      export default memberstack
      
      // auth.js
      
      import memberstack from "/lib/memberstack.js"
      
      const memberstack = window.$memberstackDom;
      const redirectTo = (path) => { window.location.href = path }
      
      // use snippet below if using a form
      const signupMember => ({ email, password }) =>
        memberstack
        .signupMemberEmailPassword({ email, password })
        .then(({ data: member }) => { redirectTo("/onboarding") })
      
      const handleSubmit = (e) => {
        e.preventDefault();
        let email = e.target.email.value
        let password = e.target.password.value
        signupMember({ email, password })
      }
      	
      // listen for form submissions
      document.getElementById('signup-form')
      .addEventListener('submit', handleSubmit);
      
      ////////////////////////////////////////////
      
      // use snippet below if using a modal
      const signupButton = document.getElementById('signup');
      
      signupButton.addEventListener('click', () => {
        memberstack.openModal('SIGNUP').then(({ data }) => {
          memberstack.hideModal();
          redirectTo('/onboarding')
        });
      });
      
      
      // signup.html 
      
      <body>
        <main>
          <h1>Sign Up</h1>
          <br />
          <form id="signup-form">
            <input name="email" type="text" />
            <input name="password" type="text" />
            <button type="submit">Sign Up</button>
          </form>
          <!-- or use a button below to trigger a modal instead -->
          <button id="signup">Sign Up</button>
        </main>
        <script type="module" src="./auth.js"></script>
      </body>
      

Logging a Member Out

await memberstack.logout()

Subscribing to Changes in Auth State

You can use the onAuthChange listener to track changes in the currently authenticated member, such as signup, login, and log out events.

memberstack.onAuthChange(member => {
  if (member) // Member is authenticated
  if (!member) // Member is not authenticated
})

The method returns an object that allows you to unsubscribe the current listener. After unsubscribing, Memberstack will no longer send auth updates to the callback function.

const listener = memberstack.onAuthChange(member => {...})

listener.unsubscribe()

Member Management

Getting The Current Member

The getCurrentMember method can be used to fetch the currently logged in member. If a persisted authenticated member is available in storage, Memberstack will return that object first. Otherwise we make an asynchronous API call to our severs to query the member.

let { data: member } = await memberstack.getCurrentMember()

// or 

memberstack.getCurrentMember().then(({ data: member }) => {
  if(member) {
    // do something with member data here
    // init 3rd party analytics, etc.
  }
})

See our DOM package reference for more details on the getCurrentMember method and the Member object.

Updating The Current Member

  • Update member custom fields

    updateMember allows you to update the custom fields on member.

    await memberstack.updateMember({
        customFields: {
          country: "Canada"
        }
    })
    
  • Update member email or password

    updateMemberAuth allows you to update a member's email or password.

    await memberstack.updateMemberAuth({
      email: "nicolas@gmail.com"
    })
    
    await memberstack.updateMemberAuth({
       oldPassword: "...",
       newPassword: "..."
    })
    

Examples

Basic

This example shows how to fetch an authenticated member, gate a protected page with an onAuthChange listener and write a welcome message to the DOM using member data.

Note: The example is written in ES6 module syntax w/ @memberstack/dom but you can easily add the memberstack.js static script instead and utilize the same logic.

<html lang="en">
  <body>
    <main>
      <h1>Dashboard</h1>
      <h2 id="welcome">Hello World</h2>
      <button id="logout">Logout</button>
    </main>
    <script type="module" src="./index.js"></script>
  </body>
</html>
// /lib/memberstack.js
import memberstackDOM from "@memberstack/dom";

export default memberstackDOM.init({
  publicKey: "pk_...",
});

// index.js

import memberstack from "./lib/memberstack.js"

const welcomeMessage = document.getElementById('welcome');
const logoutButton = document.getElementById('logout');

// use this logic for a re-usable Navbar
function handleMember(member) {
  if (member) {
    let name = member.customFields['name']
    welcomeMessage.innerHTML = `Welcome ${name}`
  } else {
    window.location.href="/login"
  }
}

memberstack.onAuthChange(handleMember);

memberstack.getCurrentMember().then(({ data: member }) => handleMember(member))

logoutButton.addEventListener('click', async () => {
  await memberstack.logout()
});

Was this article helpful?

Comments

10 comments

  • Comment author
    Dennis Karg

    Hey Memberstack Team, 

    I'm getting a headache from trying and trying, so I just have to ask now. 

    You write that you export 

    [...] 
    export default memberstack

    as a reusable variable in "lib/memberstack.js", for example. 
    In modular files you then import the variable with 

    import memberstack from "/lib/memberstack.js"

    and try to redeclare this unchangeable variable with

    const memberstack = window.$memberstackDom;

    I've been trying to figure this out for 2 hours now to see if I'm seeing something wrong or missing a detail, but my IDE tells me unequivocally that "memberstack" is already declared and this can't work. 

    I would appreciate a short info if and/or what I am missing here. 

    0
  • Comment author
    Memberstack Team

    Josh Lopez Do you know why this might be happening to Dennis?

    0
  • Comment author
    Josh Lopez

    Hey Dennis Karg

    can you please provide more information about your stack? Are you using react, vue, or sveltekit?

    0
  • Comment author
    Dennis Karg

    Hey Josh, thank you for your reply and question. My stack consists only of Webflow and vanilla JS with EsBuild. No framework such as Vue or React is involved. 

    From a purely logical point of view, I don't understand why I should write the following in (let's stick with the example) lib/memberstack.js: 

    import memberstackDOM from "@memberstack/dom"; 

    const
    memberstack = memberstackDOM.init({ publicKey: "pk_...", });

    export
    default memberstack;

    To then redeclare the variable "memberstack" in the "auth.js". 

    import memberstack from "/lib/memberstack.js"

    const memberstack = window.$memberstackDom;

    At the moment I've only managed it by putting the memberstack.js in the <head> (which I actually want to avoid with the DOM package) and then writing the following in my JS files to access the object: 

    // file: memberstack.js
    import memberstackDOM from '@memberstack/dom';

    export default memberstackDOM.init({
      publicKey: 'pk_sb_...',
    });
    // file: member-functions.js
    import memberstack from './memberstack';

    I really don't think I've understood something or it simply doesn't work the way I think it should.

    Thanks for your efforts Josh! 

    0
  • Comment author
    Josh Lopez
    • Edited

    Are you using the webflow package install script like:

    <script data-memberstack-app="app_id_here" 
    src="https://static.memberstack.com/scripts/v1/memberstack.js" 
    type="text/javascript"></script>

    and also using the DOM package? If so the webflow package is a wrapper around the DOM package and is included so you dont need to add both.

    I havent seen someone use Webflow with esbuild before. If I am off track maybe a video showing your project would help me understand better. 

    0
  • Comment author
    Dennis Karg

    Hey Josh, thank you for your prompt reply. The script you have mentioned is exactly that. 

    I had tried to integrate Memberstack into the project exclusively with the DOM package, but that's exactly what somehow didn't want to work (because maybe it's not possible or I made a mistake?) - maybe because of the test mode? 

    I don't use EsBuild in context with or in Webflow, only for all custom code, which I bundle and thus integrate into my project via <script async src="xyz.com/app.js"></script>. 

    My basic goal is to use the DOM package instead of the script from "https://static.memberstack.com/scripts/v1/memberstack.js" to run the frontend code from Memberstack exclusively within my bundled JavaScript - just like I use GSAP in these, for example. 

    I would like to record a video to help you understand it better, but the project is still at a very early stage and I don't want any information to get out yet. If I do, I'll have to send it to you directly. 

    0
  • Comment author
    Josh Lopez

    ah the https://static.memberstack.com/scripts/v1/memberstack.js script is a wrapper around the DOM package so it comes with it. Meaning you dont have to initialize it. You would only need to use: 

    window.$memberstackDom

    Try something like this:

    <script> 
    window.$memberstackDom.getCurrentMember().then(({ data: member }) => {
    if (member) {
    console.log(member) 
    } else {
    // do logged out logic here
    } })
    </script>
    0
  • Comment author
    James Jeffreys

    Hey Josh Lopez Memberstack Team,

    It might be worth adding something about v1.0 vs v2.0.
    I am getting a little confused because of this URL you have: https://static.memberstack.com/scripts/v1/memberstack.js.

    Does the v1 in it suggest it's for Memberstack v1.0? If you want to build straight on v2.0, should we use a different URL?

    0
  • Comment author
    James Jeffreys

    I also just realised that you're including the link in angle brackets in the code which is not correct syntax afaik, so perhaps that was meant to mean <change as relevant>.

    I can't easily find references on what that maybe should be changed to, so I am gonna have to just play around, but this could be less confusing in this help doc I think. Thanks!

    0
  • Comment author
    Josh Lopez

    We have a 1.0 to 2.0 conversion doc here

    0

Please sign in to leave a comment.