Is there a way to have user's fill out required profile fields after registration?

Marco
Marco Vanilla Sprout

Hello!

Our community has gone through a couple of iterations of required profile fields for our users, for tracking purposes. The problem is that when you add a new required profile field, users aren't notified about it. Is there a way to have a prompt show up letting the user know they must fill out the required profile fields to continue?

Another issue is that when we have to edit roles for specific users with empty required profile fields, you can't edit the role until you enter something for them. There doesn't seem to be a way to bypass this, creating inaccuracies when forced to fill out a profile field.

Thanks!

Answers

  • Rav Singh
    Rav Singh Vanilla Sundae

    1000% agree with this.

    I would absolutely love the ability to prompt users to complete missing custom profile fields.

    We're leveraging automation rules for users to follow our various product announcements categories based on their profile field selection. This is combined with default notification preferences which allows us to communicate important product information to the relevant members.

    Unfortunately, we have thousands of users who registered for our Community before custom profile fields were active. It would be great to be able to prompt these users to complete missing profile field info upon their next login.

  • I know for my own community, adding a required field means that someone who already has an account is required to complete those fields the next time they log in before resuming normal community access. I am not sure whether that is due to the SSO type I have or if it is the normal behavior of Vanilla, but can ask! If it is an integrated function, I would suggest adding a Guest-visible html widget to the landing page with a notification that users will be asked to complete some profile fields when they log in next, just to help alleviate any confusion. I will check to see if I can get an answer about whether that is normal functionality and update my response :)

  • @Marco and @Rav Singh - looks like it is a Vanilla function, so it will occur with your communities out of the box…yay! I am not sure if it works the same on staging, but I might start there to do a test and see if it works the same. That way you can see the UX and create that guest visibile message to help smooth over any frustrations. Hope this helps!

  • paddykelly
    paddykelly HLV Staff
    edited January 10 #5

    I am so glad to see this question because some brilliant user has made a post about this. (It was me 😌). Give a nudge to users who are still using the custom profile avatar. That post was just about detecting if your user's had not added a photo and giving them a prompt to do so. But it could be easily adapted for any profile data that is missing.

    You create a Custom HTML widget with JavaScript that does an API call to the current user's profile to see what data is missing.

    In this iteration the JavaScript would have to be a bit different than my other post:

    class UserProfile {
        
        constructor(e) {
            this.vanilla = e;
            this.shadowRoot = customHtmlRoot.shadowRoot;
            this.displayElementID = "MyMissingInfo";
            this.displayElement = this.shadowRoot.getElementById(this.displayElementID) ?? false;
            this.currentUserId = this.vanilla.getCurrentUser().userID ?? 0;
            this.verifyUserProfile();
        }
    
    
        verifyUserProfile = () => {
            // If the current user is a guest, abort.
            if (this.currentUserId === 0 ) {
                return;
            }
    
            // Do an API call to the current user's profile.
            // Because we want profile fields, call the user by the current user's userID
            // and expand the API request.
            this.vanilla.apiv2.get(`/users/${this.currentUserId}?expand=all`).then((res) => {
                console.log(res.data);
                // Check if they current user has a default avatar...
                if (this.hasDefaultPhoto(res.data.photoUrl)) {
                    // If so, display the avatar in the message, and make the message visible.         
                    this.displayCurrentPhoto(res.data.photoUrl);
                }
                
                // res.data.profileFields will only contain fields that have data
                // if a user didn't fill in a field it will be absent from this list
                // it won't just be there but blank. So, if a field is absent that you 
                // want the user to fill in, test for it and alert the user.
                if (!res.data.profileFields?.favouriteHockeyTeam) {
                    this.promptForHockeyTeam();
                }
            }).catch((err) => {console.log('Looking for the UserProfile update message? It failed to load. Error message: ', err)});
        }
    
    
        // Test for default photo or avatar.
        hasDefaultPhoto = (photo) => {
            console.log("Current Photo", photo);
            if (photo.endsWith("defaulticon.png") || photo.includes("/uploads/defaultavatar/") || photo.includes("gravatar.com")) {
                return true;
            }
            return false;
        }
    
    
        // Display the current default avatar they are using in the message and set the message to show.
        displayCurrentPhoto = (photo) => {
            console.log('this ShadowRoot', this.shadowRoot)
            const imageTag = this.shadowRoot.getElementById('profilePhoto');
            console.log('Photo passed to displayCurrentPhoto', photo);
            console.log('ImageTag found', imageTag);
            imageTag.src = photo;
            // Show the missing photo messagge.
            this.diplayPhotoMsg();
            // Show the whole widget.
            this.displayPrompt();
        }
    
        // Create and show a message.
        promptForHockeyTeam = () => {
            const hockeyTeamMsg = this.shadowRoot.getElementById('hockeyTeamMsg');
            // Populate the message.
            hockeyTeamMsg.innerHTML = "Also, we can't go on like this. We need to know your favourite hockey team.";
            // Show the message.
            this.diplayProfileFieldsMsg();
            // Show the link to the Edit Profile Fields.
            this.diplayProfileLink();
            // Show the whole widget.
            this.displayPrompt();
        }
    
        // Show message of the missing photo.
        diplayPhotoMsg = () => {
            this.shadowRoot.getElementById('PhotoMsgWrap').classList.replace('hide', 'show');
        }
    
        // Show message of the profile fields.
        diplayProfileFieldsMsg = () => {
            this.shadowRoot.getElementById('ProfileFieldsMsgWrap').classList.replace('hide', 'show');
        }
    
        // Show the link to the profile page
        diplayProfileLink = () => {
            this.shadowRoot.getElementById('profileLink').classList.replace('hide', 'show');
        }
    
        // Display the whole prompt.
        displayPrompt = () => {
          this.displayElement.classList.replace('hide', 'show');
        }
    }
    
    
    onVanillaReady((e) => {
        new UserProfile(e);
    });
    

    Notice that the condition to know if the user has input their favourite hockey team looks like this:

    if (!res.data.profileData?.favouriteHockeyTeam) {
    

    The ! means if something is not there and the ?.favouriteHockeyTeam the question mark tell the browser that if the JSON key does not exist, don't throw an error, just return null.

    The HTML looks like this:

    <div class="myMissingInfo hide" id="MyMissingInfo">
        <div id="PhotoMsgWrap" class="hide">
            <h2 class="messagecontent title">Is this how you want to be seen?</h2>
            <div class="imageWrapper"><a href="/profile/picture" title="Click to update photo."><img src="" class="profilePhoto" id="profilePhoto"></a></div>
            <div class="messagecontent message">
                I see you are using a default avatar. Don't be shy, show your true colors and help us know you better.
            </div>
            <div class="profileLinkWrapper"><a href="/profile/picture">Update Your Photo.</a></div>
        </div>
        <div id="ProfileFieldsMsgWrap" class="hide">
            <h2 class="messagecontent title">We're missing important information about you.</h2>
            <div id="hockeyTeamMsg" class="messagecontent message"></div>
        </div>
        <div id="profileLink" class="profileLinkWrapper hide"><a href="/profile/edit-fields">Update My Profile Data</a></div>
    </div>
    

    Good luck adapting this to your specific needs. It doesn't have to be your favourite hockey team, and can also be your favourite hockey goalie, or forward. I give full permission.

  • Marco
    Marco Vanilla Sprout
    edited December 2024 #6

    Thanks, @paddykelly! We'll take a look at this.

    @Heather Wendt Do you know how we would enable it if it is out of the box? Is it automatically on unless there are SSO changes?

  • Hi @Marco - are you making any of the fields required? Once that is toggled on, it should work with both out of the box and SSO…basically a pause in the access process until the required field is completed and saved. Let me know if you are seeing a different experience!

  • Rav Singh
    Rav Singh Vanilla Sundae

    Hey @Heather Wendt

    Do you know if the above is specific to sites that use SSO?

    We don't use SSO on our Community but we do have required custom profile fields. In our case they'll only be prompted to complete any required missing fields if they attempt to edit their profile information.

  • Marco
    Marco Vanilla Sprout

    I don't believe this is working the way described with our SSO. They are also toggle on required fields.

  • Hey everyone!

    The expected behavior here is for any required profile fields to force an entry only when a user is editing their profile. It should not force any completion of profile fields when logging in.

    I hope this helps!

  • Marco
    Marco Vanilla Sprout

    Ah, that clears things up. Was hoping to have it require users to update all required profile fields at login. So, only IF a user is missing required profile fields AND enters their profile for editing, it will force them to complete it to continue?

  • Rav Singh
    Rav Singh Vanilla Sundae

    Yep correct @Marco, that's what occurs on our site for members who haven't completed a required profile field.

    Hey @paddykelly

    Thanks for the above info, I've tried giving this a go in our staging site today and just want to understand the best way to adapt this to our specific profile fields.

    I copied your code to an HTML widget and updated ?.favouriteHockeyTeam to the API label of the specific profile field that I'd like users to complete if missing. I've also edited the hockeyTeamMsg.innerHTML message for relevancy to our profile field. I've left everything else the same as your code.

    I'm guessing I haven't done something correctly as the widget displays as below to all members regardless if they have the default profile avatar and/or completed the specific profile field or not.

    Are you able to advise on what aspects of your code I need to amend (and with what data from our site) so the widget only displays to members who have not completed a specific profile field?

    Thanks so much 🙏

  • paddykelly
    paddykelly HLV Staff
    edited January 9 #13

    This is my bad, @Rav Singh . I forgot one simple part. Notice how I put a class hide on the "MyMissingInfo" HTML element that houses this whole widget. I was supposed to give you the CSS that goes with this widget that would hide the whole widget by default, unless it found out that a user needed to see it. Then it would remove that hide class and replace it with show

    // Display the whole prompt.
    displayPrompt = () => {
      this.displayElement.classList.replace('hide', 'show');
    }
    

    (Part of) this CSS hides hide and shows show :

    .myMissingInfo {
        min-height: 200px;
        width: 100%;
        box-shadow: 1px 1px 3px 3px #eee;
        border-radius: 6px;
        padding: 15px 0;
        flex-direction: column;
    }
    
    .myMissingInfo h2.messagecontent.title {
        font-size: 20px;
        text-align: center;
        margin-bottom: 18px;
    }
    
    .hide {
        display: none;
    }
    
    .show {
        display: block;
    }
    
    .messagecontent {
        display: flex;
        flex: 1;
        margin: 5px 15px;
    }
    
    .myMissingInfo .imageWrapper {
        position: relative;
        overflow: hidden;
        border-color: rgba(170, 173, 177, 0.3);
        border-width: 1px;
        border-style: solid;
        border-radius: 50%;
        margin: auto;
        max-height: 60px;
        max-width: 60px;
    }
    .imageWrapper img {
        max-height: 60px;
        max-width: 60px;
    }
    
    .messagecontent.warning {
        background-color: #fff8ce;
        padding: 6px 7px;
    }
    
    .profileLinkWrapper {
        width: 100%;
        margin: 30px auto;
        text-align: center;
        clear: both;
    }
    
    .profileLinkWrapper a {
        padding: 5px 10px;
        border-width: 1px;
        border-style: solid;
        border-radius: 6px;
        text-decoration: none;
        margin: auto;
    }
    
    .profileLinkWrapper a {
        background-color: #037dbc;
        border-color: #037dbc;
        color: #ffffff;
        font-weight: 600;
    }
    
    

  • Rav Singh
    Rav Singh Vanilla Sundae

    Thanks again for your help with this @paddykelly

    Unfortunately, I don't think I'm technically adept enough to get this working for our own specific My Reckon Software profile field 😔

    I can get the widget working but it seems to appear regardless if the member has a custom or default profile pic AND if the profile field has been completed or not. Rather than combining the widget to check both the profile pic and custom profile field, is there any way for it just to check a designated profile field only?

    I'm quite sure the issue is on my end, as I’m not familiar with reading or working with code, so I might have to let this one go.

    Thanks for your efforts in helping with this though, its greatly appreciated.

  • Hey @Rav Singh , thanks for pointing that out. I made some changes to the HTML, JavaScript and CSS in my posts above to accommodate for this. The problem was that the photo messaging was showing no every time we show the widget, which we don't want. So you can see above I put all the HTML for the photo messaging in a div

    <div id="PhotoMsgWrap" class="hide">
    

    and all the messaging for the profile field messaging in another div

    <div id="ProfileFieldsMsgWrap" class="hide">
    

    so that they can be shown and hidden independently. This means I had to change two lines in the CSS. What was:

    .myMissingInfo.hide {
        display: none;
    }
    
    .myMissingInfo.show {
        display: flex;
    }
    

    is now just

    .hide {
        display: none;
    }
    
    .show {
        display: block;
    }
    

    (NOTE I changed .show from display: flex to display: block).

    You should also update your JavaScript as well because I had to add functions to show each block separately.