Introduction
Memberstack can be integrated into a Vanilla JS environment in two distinct ways:
- Utilizing the
@memberstack/dom
NPM package. - 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 ourms-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.
- Ease of use with
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()
});
Comments
10 comments
Hey Memberstack Team,
I'm getting a headache from trying and trying, so I just have to ask now.
You write that you export
as a reusable variable in "lib/memberstack.js", for example.
In modular files you then import the variable with
and try to redeclare this unchangeable variable with
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.
Josh Lopez Do you know why this might be happening to Dennis?
Hey Dennis Karg
can you please provide more information about your stack? Are you using react, vue, or sveltekit?
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:
To then redeclare the variable "memberstack" in the "auth.js".
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:
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!
Are you using the webflow package install script like:
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.
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.
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:
Try something like this:
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?
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!
We have a 1.0 to 2.0 conversion doc here.
Please sign in to leave a comment.