Setting up SA5 Memberships for use with custom JavaScript

These are the steps I followed to try and call user data using custom JavaScript instead of data binding:

  1. Add this code in the site wide HEAD section under the initial SA5 Membership library:
<!-- Sygnal Attributes 5 | Memberships | User Info Changed Event -->
<script>
window.sa5 = window.sa5 || [];
window.sa5.push(['userInfoChanged', 
  (user) => {
    console.log("USER INFO CHANGED", user); 
  }]); 
</script> 
  1. Add this code in the site wide HEAD section under the code from Step 1:
<script>
async function userInfoUpdatedSiteCallback(user) {
  if (window.userInfoUpdatedPageCallback)
  	window.userInfoUpdatedPageCallback(user);
} 
</script>
  1. Add this code on the page you’d like to call the user data and include what you’d like to do with that data:
<script>
async function userInfoUpdatedPageCallback(user) {
 if(!user.user_data_loaded.custom_fields) {
   	document.getElementById("this-text-block").textContent = user.name;
    	return;
  	console.log("page callback."); 
	}
}
</script>

To test this, I added the following code to Step 3 (as seen above):

document.getElementById("this-text-block").textContent = user.name;

I expected the text block to show the user’s name, but nothing happens.

Read-Only:
https://preview.webflow.com/preview/movewithcolour?utm_medium=preview_link&utm_source=designer&utm_content=movewithcolour&preview=542c10a9ca0dca69f56859b3133760c0&pageId=651b8f696e86b9967982ae54&workflow=preview

Staging:
https://movewithcolour.webflow.io/dashboard-test

User Account:
nathan@colourbeat.com
password

That code block you have in #1 would need to call your function userInfoUpdatedSiteCallback in order for your function to execute, and you can still do that but that approach should be simplified for SA5.

Not sure how much the community has BETA’d it, but the userInfoChanged handler should support multiple handlers, e.g. site-level and page-level simultaneously.

Therefore you should be able to just use the code block in #1, put your code in it, and place it in the page you want.

e.g.;

<!-- Sygnal Attributes 5 | Memberships | User Info Changed Event -->
<script>
window.sa5 = window.sa5 || [];
window.sa5.push(['userInfoChanged', 
  (user) => {
    if(!user.user_data_loaded.custom_fields) {
     	document.getElementById("this-text-block").textContent = user.name;
    	return;
	}
  }]); 
</script>

These APIs are quite simple but they do require a little bit of code knowledge. You were very close. Give this a try and see how it works.

We use page-level handlers on some client sites but I’m not sure how widely the community has BETA’d this new feature.

Thank you for the quick reply, @memetican!

I did what you’ve suggested but unfortunately it hasn’t worked.

Here’s the current set up I now have based on how I interpreted your reply.

  1. Add the initial SA5 Memberships code to the site wide head:
<!-- Sygnal Attributes 5 | Memberships -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/sygnaltech/webflow-util@5.3.4/dist/css/webflow-membership.css"> 
<script defer src="https://cdn.jsdelivr.net/gh/sygnaltech/webflow-util@5.3.4/dist/nocode/webflow-membership.js"></script>

<script>
window.sa5 = window.sa5 || [];
window.sa5.push(['getMembershipConfig', 
  (config) => {
    // Apply any configuration settings here
    // such as access groups 
    return config;
  }]);
</script>
  1. Add this code to the head of the specific page on which you want to call user data and run my test:
<!-- Sygnal Attributes 5 | Memberships | User Info Changed Event -->
<script>
window.sa5 = window.sa5 || [];
window.sa5.push(['userInfoChanged', 
  (user) => {
    if(!user.user_data_loaded.custom_fields) {
     	document.getElementById("this-text-block").textContent = user.name;
    	return;
	}
  }]); 
</script>

It’s a simple test page so there’s nothing else that should be interfering. Any ideas?

I’m not sure what this is in this context. Ah I see now, you just copied from the docs- you need to read how to configure it for the fields you want.

I’ve updated the best practices page.

If that doesn’t work, again your previous approach was solid, you just need to call your handler function so your code will execute.

Apologies. I’d left (!user.user_data_loaded.custom_fields) in there by mistake instead of changing it to (!user.user_data_loaded.account_info) for this test. The test is simply to use custom script to get a the user’s name to appear in a single text field as per the test page.

I’ve read all the of documentation (over, and over, and over…).

The question remains the same: are those two steps all you need to make a user’s name appear in a text field using custom script? It’s unclear in the documentation.

I also went back to the three step approach as per the initial post and called the userInfoUpdatedSiteCallback function in Step 1 as you suggested:

<!-- Sygnal Attributes 5 | Memberships | User Info Changed Event -->
<script>
window.sa5 = window.sa5 || [];
window.sa5.push(['userInfoChanged', 
  (user) => {

    userInfoUpdatedSiteCallback();

    console.log("USER INFO CHANGED", user); 
  }]); 
</script>

… but this approach doesn’t work either.

If the three step and the two step approach don’t work, I’m really at a loss here. I was hoping this would be as easy as setting up the data bind, i.e. ‘Do this. Do that. Voila.’ :sweat_smile:

It’s pretty clear, that function is called when the data is available, and the original example had a console.log so you can see and check the data in the browser console. Once you have it you can do whatever you like with it.

There’s not much I can add to that.

Check the console, you should see “USER INFO CHANGED” along with the user object.

SA5’s databinding uses exactly the same process internally. It just registers its own userInfoChanged handler. And a whole bunch of others… data binding is complex.

Btw in JS ! means “NOT” as in if the account_info is NOT loaded.
For what you’re trying to do logically that wouldn’t work.

Main thing is to user your brower console and console.log so you can see what’s happening and debug your custom code.

Fortunately, removing the ‘!’ made the two step process work :white_check_mark:

I understand the logic of ‘!’, but I only see how that got in the way now that you pointed it out. That ‘!’ came from the code in your documentation, which I copied across. A learner like me follows the documentation and uses code as it is provided (often times more verbatim than you might anticipate).

I really do appreciate your support with this, and all of the time you put into this when you aren’t getting paid for the support you offer on here, but I don’t think saying ‘It’s pretty clear’ when someone who’s learning says ‘It isn’t clear’ is very helpful :frowning_face:

I can help make it clearer for people like me though!

Here is a simple step-by-step for anyone looking to set up SA5 Memberships with access via custom JavaScript:

STEP 1

Add this code to the site wide HEAD section under the initial SA5 Membership library:

<!-- Sygnal Attributes 5 | Memberships -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/sygnaltech/webflow-util@5.3.4/dist/css/webflow-membership.css"> 
<script defer src="https://cdn.jsdelivr.net/gh/sygnaltech/webflow-util@5.3.4/dist/nocode/webflow-membership.js"></script>

<script>
window.sa5 = window.sa5 || [];
window.sa5.push(['getMembershipConfig', 
  (config) => {

    // Apply any configuration settings here such as
    // access groups

    return config;
  }]);
</script>

STEP 2

Add this code to the HEAD of the specific page on which you want to call basic user data (name, email, accepts communications, alt user ID):

<!-- Sygnal Attributes 5 | Memberships | User Info Changed Event -->
<script>
window.sa5 = window.sa5 || [];
window.sa5.push(['userInfoChanged', 
  (user) => {
    if(user.user_data_loaded.account_info) {

     // Your code here, using user.name, user.email, 
     // user.accept_communications or user.user_id_alt
     // to get the data you want

     return;
	}
  }]); 
</script>

If you want to use data from custom fields, change:

if(user.user_data_loaded.account_info) {

to:

if(user.user_data_loaded.custom_fields) {

and in ‘Your code here…’ use user.data["slug"] in your code to get that data (where “slug” is the slug of that field as it appears in the user account settings of your site).

Voila! :grin:

Yes, I can see it confused you which is why I’ve removed that code example. It was for a more advanced use case than most devs would need. But like all code examples, it requires a basic understanding to see and apply the principles you need for your own use case.

In general, if you copy / paste examples, it’s very unlikely they’ll be setup to do what you want, especially when they’re under a big red “this is outdated SA4 code” banner :wink:

I’m very glad you’ve gotten the SA5 callback to work at the page level as I’ve designed it, you’re the first to officially report using that advanced feature, so I’ve updated the Best Practices page with that as the recommended approach. Much appreciated.

:thinking: It wasn’t meant at all offensively. It’s just not possible to make the examples simpler or clearer without writing every possible example someone could possibly consider. There’s nothing to remove and nothing to add.

I appreciate the feedback though, and I’ll think on that. 90% of my work right now is with designers and agencies who need coding or integrations, and don’t have that knowledge in-house.

98% of SA5 is nocode, but we commonly put in hooks for advanced APIs when we want to customize the feature for a specific situation. We’ve only started publishing some of those API’s to the community, but they’re just not suitable for most non-devs to work with.

Finsweet has the same issue, a few of their tools have APIs and they’ve had to start charging for a support community because those edge cases always require custom code.