Customizing the Registration Experience

This section provides walkthroughs for many common use cases, and it is organized in a Question/Answer format.

Prerequisites

Before reading this section, you should already be familiar with the following concepts:

Common Questions and Use Cases

Customizing what information is gathered during registration

Customizing the Flow of the User Experience

Customizing validation and other logic

Customizing the style/aesthetics of your forms

Customizing Transactional Emails

Customizing language/locale

Managing Multiple Sites and Brands

Customizing What Information Is Gathered during Registration

How do I create a custom field, in general?

Fields are means of connecting data input from the user to the Capture database.

Therefore, unlike forms, fields are defined in three places:

  1. The Schema
  2. The Flow
  3. The HMTL/Markup (as JTL tags)

To create a custom field, you need to make changes not just the Flow and HTML/Markup, but also possibly in the Schema because fields need to map to an object in the database (Schema). You can learn more about the Schema in our documentation on Data Management.

  1. Identify the name of the schema attribute you want to associate with your new field Multiple fields are allowed to reference the same schema attribute, so you have the option of using an existing schema attribute. Examples of this are the emailAddress and signInEmailAddress fields that come with the default registration Flow; both map to the email attribute in the schema. However, if you do not wish to map your data to an existing schema attribute, then you must create it first. You can create a schema attribute by making a POST request to the /entityType.addAttribute Janrain Entity API endpoint.

  2. Add the new field to the Flow There are many field types and validations that can define a field. Regardless of the field type, however, you create a new field by making a POST request to the /config/{app}/Flows/{Flow}/locales/{locale}/fields Configuration API endpoint. An example request body is shown below:

    {
      "label": "foo",
      "name": "myCustomTextField",
      "placeholder": "foo",
      "schemaAttribute": "displayName",
      "tip": "foo",
      "type": "text",
      "validation": [
        {
          "rule": "required",
          "value": true,
          "message": "foo"
        }
      ]
    }
    

    We do not recommend using the /config/{app}/flows/{flow}/fields endpoint to create new fields; not all field types (such as drop-down fields) support being created at that endpoint.

  3. Update the relevant form(s) to include the field To make your new field visible to the user, you must add it to a form in the Flow and then include that field’s JTL tag in that form’s markup. Please refer to this document’s section on how to generally add a field to a form.

How do I remove a custom field, in general?

“Removing” a field can be a bit ambiguous, as fields can be “removed” in two ways:

  • Updating a Form to remove the field from the form
  • Deleting the field completely, which automatically removes it from all forms

Fields are defined as independent objects in the Flow, and can optionally be included on forms. Thus, removing a field from a form doesn’t delete the field; it only removes that field from the form. Removing a field from a form is described in this section.

If, however, you want to completely remove a field definition then you will need to delete the field from the Flow. Note, this will also remove the field from all forms. To delete a field, first make a GET call on the /config/{app}/flows/{flow}/fields/{field} endpoint to confirm you are viewing the correct field. Then, make a DELETE call on the same endpoint to delete the field. Note that you will need to also add the force URL parameter to the DELETE call, with the value true.

How do I add/remove a field on a form, in general?

Forms are how your user interacts with your website and submits registration information. On the backend, forms function to group together fields (input elements), and are defined in two places:

  1. The Flow
  2. The HMTL/Markup (as @@@Janrain Templating Language (JTL)@@@ tags)

Therefore, to add or remove fields on a form, you need to make changes in both those places. You can find more information on the technical nature of forms and their relationship to screens in the Screens Technical Overview. This is how generally you add/remove fields on forms:

  1. Identify the form you wish you modify. You can identify the name of the form by looking for the {* #formName *}...{* /formName *} JTL markup. In the forgotPassword screen example below, you can see the form name is forgotPasswordForm.

    <div style="display:none;" id="forgotPassword">
        <div class="capture_header">
            <h1>Create New Password</h1>
        </div>
        <h2>We'll send you a link to create a new password.</h2>
        {* #forgotPasswordForm *}
            {* signInEmailAddress *}
            {* someField *}
            <div class="capture_footer">
                <div class="capture_left">
                    {* backButton *}
                </div>
                <div class="capture_right">
                    <input value="Send" type="submit" class="capture_btn capture_primary">
                </div>
            </div>
        {* /forgotPasswordForm *}
    </div>
    
  2. Add or remove the field from the form, using the Configuration API. You will be using the /config/{app}/Flows/{Flow}/forms/{form} endpoint to add or remove a field on a form.

    1. GET the form first, so that you have the form definition JSON. This is also a good opportunity to check if the field you wish to add/remove isn’t already defined on the form. Below is an example response for a GET of the forgotPasswordForm:

      {
        "_self": "/config/v86cchggr5cdvbfh7ydk8s63zz/Flows/myCoolFlow/forms/forgotPasswordForm",
        "fields": [
          {
            "_self": "/config/v86cchggr5cdvbfh7ydk8s63zz/Flows/myCoolFlow/fields/signInEmailAddress",
            "name": "signInEmailAddress",
            "required": false
          },
          {
            "_self": "/config/v86cchggr5cdvbfh7ydk8s63zz/Flows/myCoolFlow/fields/someField",
            "name": "someField",
            "required": false
          }
        ]
      }
      
    2. Make a PUT request, specifying the form JSON in the body of your request. You can exclude keys preceeded by underscores (such as _self), however this is not required. If you were removing a field (say, the someField field in the example), then the request body may look like this:

      {
        "fields": [
          {
            "name": "signInEmailAddress"
          }
        ]
      }
      

      If you were adding a field to the form, then the request body might look like this:

      {
        "fields": [
          {
            "name": "signInEmailAddress"
          },
          {
            "name": "someField"
          },
          {
            "name": "someNewField"
          }
        ]
      }
      

      Note, if you are adding a field to the form then it must already exist in the Flow. If it does not, then you need to create a new field first.

  3. Update your markup to include/exclude the field JTL Update your screen HTML to include or exclude the field’s JTL tag. For example, adding someNewField’s JTL tag to the forgotPasswordForm by adding the {* someNewField *} markup:

    <div style="display:none;" id="forgotPassword">
        <div class="capture_header">
            <h1>Create New Password</h1>
        </div>
        <h2>We'll send you a link to create a new password.</h2>
        {* #forgotPasswordForm *}
            {* signInEmailAddress *}
            {* someField *}
            {* someNewField *}
            <div class="capture_footer">
                <div class="capture_left">
                    {* backButton *}
                </div>
                <div class="capture_right">
                    <input value="Send" type="submit" class="capture_btn capture_primary">
                </div>
            </div>
        {* /forgotPasswordForm *}
    </div>
    

How do I customize an existing field?

To modify an existing field, you will utlize the /config/{app}/Flows/{Flow}/locales/{locale}/fields/{field} Configuration API endpoint. We do not recommend using the /config/{app}/Flows/{Flow}/fields/{field} endpoint to update a field definition; behavior is not consistent across all fields (such as for drop-down fields).

  1. Make a GET call to acquire the current field definition.

  2. Modify the field definition, and then make a PUT call with the modified field definition in the body of your request. You can exclude elements preceded by an underscore, such as _self.

How do I add a field for email, phone number, etc. requiring regex validation?

Fields such as email, phone number, zip code, etc. that require validation against a regular expression pattern can be implemented in two different ways:

  • Using a Pre-Built Validation Rule, or
  • Implementing Custom Regex

Pre-Built Validation Rule

Using a Pre-Built Validation Rule automatically provides both client and server-side validations to a field, and does not require you to write your own regular expression (we’ve done that for you). Plus, to implement a Pre-Built Validation Rule, you only need to implement a Flow change, adding or updating a field to have a validation object with the format rule.

{
    "label": "Your Email",
    "name": "myCustomEmailField",
    "schemaAttribute": "email",
    "validation": [
        {
          "rule": "format",
          "value": "email",
          "message": "Your email was not formatted correctly"
        }
    ]
}

A Pre-Built Validation Rule can be “email”, “phone”, “alphanumeric” or any number of other pre-built regular expressions. You can browse the validations section of our Configuration API documentation to find definitions that fit your use case. Finally, remember to add the new field to the relevant forms in order to utilize it.

Custom Regex

To implement custom regular expressions, you need to make three changes: a Flow change , a client-side change, and a API client settings change.

  1. In your Flow, add or update a field such that it has a validations object with the following rules:

    • clientFunctionName - This will be the name of the client-side JavaScript function that you will register with the Registration UI client-side.
    • serverRegexSetting - This will be the name of the API client setting that contains the regular expression.

    When an user is filling out a form incorrectly and has not yet submitted it, they will instantly see an error message displayed. The clientFunctionName corresponds to a JavaScript function defined client-side (see the next step), which is what enables this instantaneous feedback to the user.

    On the other hand, if after submitting a form a field fails validation then the user will see an error message displayed after the form is submitted. This is a slower mechanism for feedback, but helps to ensure data integrity. The serverRegexSetting corresponds to this server-side feedback.

    You can see this behavior by giving meaningful messages like in the example set of validation rules below, and trying to trigger each separately. Note, however, that in practice both messages will be the same because the user doesn’t need to know which type of validation that it failed (only that it failed).

    {
        "label": "Your Member Number",
        "name": "memberNumber",
        "schemaAttribute": "professionalInfo.memberNumber",
        "validation": [
            {
              "rule": "clientFunctionName",
              "value": "validateMemberNumber",
              "message": "Your member number fails client-side validation"
            },
            {
              "rule": "serverRegexSetting",
              "value": "member_number_regex",
              "message": "Your member number fails server-side validation"
            }
        ]
    }
    

    Note that, generally speaking, we recommend implementing both clientFunctionName and serverRegexSetting rules to enforce both client-side and server-side validation. If, however, you are implementing your own client-side validation then you can exclude the clientFunctionName validation rule.

  2. In your client-side markup, you will need to register the clientFunctionName with the Registration UI. Below is an example; you can find more information on this function in our JS API documentation.

    function janrainCaptureRegistration UIOnLoad() {
        function validateMemberNumber(name, value) {
            var expression = /\d{5,7}/;
            return expression.test(value);
        }
        //
        janrain.capture.ui.registerFunction('validateMemberNumber', validateMemberNumber);
        //
        janrain.capture.ui.start();
    }
    
  3. Add the name of the regexServerSetting to your API client settings. Note that you must exclude the leading/trailing forward-slash. Generally, we recommend adding these settings on a per-client basis, as is depicted below. Please see Clients and Settings for more information on clients and settings.

    Adding a regex setting to a client

  4. Finally, remember to add the new field to the relevant forms in order to utilize it.

How do I add a drop-down/list-of-values field to a form?

To create a drop-down field, add or update a field such that is type “select” and has an options object containing a list of select options. See the example below. Finally, remember to add the new field to the relevant forms in order to utilize it.

    {
      "label": "Favorite Food",
      "name": "favoriteFood",
      "options": [
        {
          "selected": true,
          "label": "",
          "value": ""
        },
        {
          "label": "Hot Dogs",
          "value": "hotdogs"
        },
        {
          "label": "Hamburgers",
          "value": "hamburgers"
        }
      ]
      "schemaAttribute": "favorites.lunchFood",
      "type": "select"
    }

How do I add a multi-select field to a form?

Currently, Janrain does not support a multi-select field type out-of-the-box. To implement this functionality, we recommend the following approach:

  1. Implement a field of type “hidden”. You will store a string representation of multi-select data in this hidden field, so make sure that the schemaId key maps to a schema attribute that is type “string”. Additionally, in your request exclude label, tip, and placeholder keys.

        "favoriteBirds": {
            "schemaId": "favorites.birds",
            "type": "hidden"
        },
    
  2. Add the new field to the relevant forms in order to utilize it.

  3. Add markup to your HTML form for the hidden field and the select options.

    {* #registrationForm *}
      {* favoriteBirds *}
      <div class="capture_form_item" id="favoriteBirds_checkboxes">
          <label>Favorite Birds:</label>
          <label><input type="checkbox" value="penguin">Penguins</label>
          <label><input type="checkbox" value="parrot">Parrots</label>
          <label><input type="checkbox" value="pigeon">Pidgeons</label>
          <label><input type="checkbox" value="chicken">Chicken</label>
          <!-- Etc... -->
      </div>
    {* /registrationForm *}
    
  4. Register a JS function to the onCaptureScreenShow event; this function will be called whenever a Janrain screen is shown to the user.

    janrain.events.onCaptureScreenShow.addHandler(function(result) {
      initFavoriteBirds(result.screen);
    });
    

    For example, this function may iterate over the input elements and attach a listener function that–when the onclick DOM event fires–updates the content of the hidden field.

    function initFavoriteBirds(screenname) {
      // Get the target elements
      var hiddenElement = document.getElementById('capture_'+screenname+'_favoriteBirds');
      var checkboxesDiv = document.getElementById('favoriteBirds_checkboxes');
    
      // Define a function to update the hidden field when the checkboxes are clicked
      var updatefavoriteBirds = function() {
        var hiddenElement = document.getElementById('capture_'+screenname+'_favoriteBirds');
        var checkboxesDiv = document.getElementById('favoriteBirds_checkboxes');
        var newValue = '';
        if (hiddenElement && checkboxesDiv) {
            // build the newValue, be it a comma-delimited string, JSON string, etc.
            // then set the value of favoriteBirds to this updated value
            hiddenElement.value = /* some string */ ;
          }
        }
    
      // Attach the updater function to the input elements
      if (hiddenElement && checkboxesDiv) {
          var checkboxes = checkboxesDiv.getElementsByTagName('input');
          for (var i=0; i<checkboxes.length; i++) {
              checkboxes[i].onclick = updatefavoriteBirds;
          }
      }
    }
    

    The above example doesn’t need to check explicitly for screen names, due to the way the Registration UI renders id attributes for field HTML; it renders id attributes with the pattern 'capture_'+screenname+'_'+fieldname. Since the conditional block only executes if it finds an html element with id attribute 'capture_'+screenname+'_favoriteBirds', then the block will only be executed for screens containing the favoriteBirds field (e.g., capture_traditionalRegistration_favoriteBirds, capture_socialRegistration_favoriteBirds, and capture_editProfile_favoriteBirds)

How do I add a date field to a form?

To create a dateselect field, add or update a field that is type “dateselect”. Before creating the field, ensure that the target schema attribute is type dateTime or date.

{
  "label": "Birthday",
  "name": "birthday",
  "schemaAttribute": "birthday",
  "type": "dateselect"
}

Once the field has been added to the Flow, it will be populated with additional keys such as yearLabel, monthLabel, dayLabel, and monthNames; these do not need to be included in the initial request. Finally, remember to add the new field to the relevant forms in order to utilize it.

Usually date fields are also created with intention to capture/enforce age gating; you can find information on how to implment this in this section.

How do I add a radio-button or checkbox to a form?

Checkbox

To create a checkbox field, add or update a field that is type “checkbox”. Before creating the field, ensure that the target schema attribute is type boolean or string (depending on your use case). See the example below. Finally, remember to add the new field to the relevant forms in order to utilize it.

    {
      "label": "I agree to receive emails and other communications",
      "name": "optIn",
      "preChecked": false,
      "schemaAttribute": "optIn.status",
      "submitValue": "yes",
      "type": "checkbox"
    }

In the above example, the preChecked and submitValue keys are optional. If prechecked is set to “true”, then the checkbox will be already checked when it is loaded on the form. The submitValue key is used to specify the submit value on a check box (that is, if a checkbox should submit a value other than “on”).

Radio-Button

To create a radio field, add or update a field that is type “radio” and also has an options object containing a list of select options. Before creating the field, ensure that the target schema attribute is type string. See the example below. Finally, remember to add the new field to the relevant forms in order to utilize it.

{
  "name": "gender",
  "options": [
    {
      "selected": true,
      "label": "Not Specified",
      "value": "Not Specified"
    },
    {
      "label": "Female",
      "value": "Female"
    },
    {
      "label": "Male",
      "value": "Male"
    },
    {
      "label": "Other",
      "value": "Other"
    }
  ],
  "schemaAttribute": "gender",
  "type": "radio"
}

How do I integrate third-party analytics into Registration?

With the Janrain Registration JavaScript API, it is possible to track registration events and send data to popular third-party analytics sites, such as Google Analytics and Adobe SiteCatalyst. An administrator can use these analytical tools to gain greater insight into how users interact with the website.

To implement third-party analytics, register an event handler that makes a call to your analytics service. You can find more information about the data made available client-side in this section. Some common events you may want to track are:

Below is an example integration with Google Analytics, which registers a function with the onCaptureLoginSuccess event to send tracking information upon successful login. There are a few key pointers to keep in mind:

  • Ensure Google Analytics code is loaded before event handlers are registered
  • Ensure event handlers are registered inside janrainCaptureWidgetOnLoad
  • Ensure events handlers are registered before calling janrain.capture.ui.start()

You can find a working example of third-party analytics in Capture on our Enterprise Demos site.

Note: If you want to implement third-party analytics for Social-Login, please see our documentation on Customizing Social Login, as it utilizes a different JavaScript API.

<script type="text/javascript">
    var _gaq = _gaq || [];
    _gaq.push(['_setAccount', 'UA-38162009-1']);
    _gaq.push(['_trackPageview']);

    (function() {
        var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
        ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
        var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
    })();
</script>

<script src="scripts/janrain-init.js"></script>

<script type="text/javascript">
    function janrainCaptureWidgetOnLoad() {
        janrain.events.onCaptureLoginSuccess.addHandler(function(result){
            _gaq.push(['_trackEvent', 'onCaptureLoginSuccess', 'fired']);
        });
        /* possibly more event handlers here */
        janrain.capture.ui.start();
    }
</script>

Customizing the Flow of the User Experience

How do I add or remove a new form?

Adding and removing forms is not currently supported via API. Please reach out to your Janrain contact via the Customer Support Portal to discuss this requirement.

You can always view the list of forms on your application by making a GET call to the /config/{app}/Flows/{Flow}/forms/{form} endpoint.

How do I personalize the user’s experience after login?

Some pieces of information, such as uuid, email and displayName, can be made available locally without the need for making API calls. This information can be used to personalize an user’s experience, such as by displaying their username upon logon.

One way to get this information is to add a function handler to the onCaptureLoginSuccess event, and then to access it via the userData object:

  janrain.events.onCaptureLoginSuccess.addHandler(function(result) {
      var displayName = result.userData.displayName;
      // Use displayName in some way...
  });

Another method is to persist this information via local storage, and then to extract it later (such as for a welcome message upon an user’s return to your site). To do this, both the setProfileCookie and returnExperienceUserData settings need to be enabled.

janrian.settings.capture.setProfileCookie = true;
janrian.settings.capture.returnExperienceUserData = ["displayName", "email"];

These will make available uuid, email, and displayName in a JSON object, inside the janrainCaptureProfileData local storage key. To access this information, you can then utilize the getprofilecookiedata JavaScript function:

var displayName = janrain.capture.ui.getProfileCookieData('displayName');

This also makes the data available in janrainCaptureReturnExperienceData, which can be accessed via the getReturnExperienceData function:

janrain.capture.ui.getReturnExperienceData('displayName');

Extending the Local Profile Information

Should you wish to make available more information than uuid, email, and displayName, then you will need to make a Flow change. To do this, make a PUT request on the userData object via the /config/{app}/Flows/{Flow} endpoint with the additional information you want made available:

{
  "userData": [
    "email",
    "displayName",
    "familyName",
    "primaryAddress.country"
  ],
  "schemas": [
    "myCoolEntityType"
  ]
}

Finally, remember to update your returnExperienceUserData setting with the appropriate attributes:

janrian.settings.capture.returnExperienceUserData = ["displayName", "email", "familyName", "primaryAddress.country"];

How do I pre-populate a form with data returned from an identity provider?

After an user authenticates socially from the signIn form, you may want to pre-populate the socialRegistration form with additional information returned from the social profile. This can be enabled for a field by adding the socialProfileData key to it.

To do this, add or update a field to include the socialProfileData key, like in the example below. Note, this key can only be added to “text”, “email”, and “textarea” type fields.

{
  "type": "text",
  "name": "myCustomTextField",
  "schemaAttribute": "displayName",
  "label": "My Custom Text Field",
  "socialProfileData": "profile.displayName"
}

Customizing validation and other logic

How do I make a field required? Optional?

To make a field required, add or update a field to include the rule “required” with value “true”, as in the example below. If you wish to make an already-required field optional, you can either remove the validation or set the value to “false”. If creating a new field, remember to add the new field to the relevant forms in order to utilize it.

{
  "label": "My Required Field",
  "name": "myRequiredField",
  "schemaAttribute": "optIn.status",
  "type": "text",
  "validation": [
    {
      "message": "This field is required",
      "rule": "required",
      "value": true
    }
  ]
}

How do I add Captcha to my forms?

To add Captcha to a form, you need to make changes in your Flow, your form markup, and your JavaScript settings.

  1. In your Flow, make a GET call to the /config/{app}/Flows/{Flow}/forms/{form} endpoint to verify you will be modifying the correct form. Once verified, add the “captcha” feature to your form and make a PUT request to the same endpoint:

    {
    "features": [
        {
          "name": "captcha"
        }
    ],
    "fields": [
        ...
      ]
    }
    
  2. In your form markup, add the {* recaptcha *} JTL tag to your form:

    <div style="display:none;" id="traditionalRegistration">
      {* #registrationForm *}
          <!-- ... -->
          {* recaptcha *}
          <!-- ... -->
      {* /registrationForm *}
    </div>
    
  3. In your JavaScript settings, add the recaptchaVersion setting to specify the version of Captcha to render:

    janrain.settings.capture.recaptchaVersion = 2; // 1 or 2
    

How do I enforce age restrictions/gating?

The birthdate field in the standard flow already supports age-gating and defaults to a minimum age of 16; simply include it on your forms where needed. What follows are instructions on how to modify this field or add additional age-gated fields.

To enforce age restrictions, you can add or update a dateselect field such that it has a validation object with the minYears (and also required) rules. Then, you can add this field to your traditionalRegistration and socialRegistration screens (the registrationForm and socialRegistrationForm forms in your Flow, respectively). Below is an example birthday field that only allows users 18 or older to register. Remember to add the new field to the relevant forms in order to utilize it.

{
  "label": "Birthday",
  "name": "birthday",
  "schemaAttribute": "birthday",
  "type": "dateselect",
  "validation": [
    {
      "rule": "required",
      "value": "true",
      "message": "Birthdate is required"
    },
    {
      "rule": "minYears",
      "value": 18,
      "message": "You must be at least 18 years old to register"
    }
  ]
}

Note, if you wish to implement site-specific (API client specific) age-gating, this is supported however is not configurable via the Configuration API. Please contact your Janrain representative for more information.

Customizing the style/aesthetics of your forms

How do I use my own stylesheets?

The Registration UI loads default stylesheets according the Janrain JavaScript settings. To include your own custom stylesheets when using the Registration UI, add the following JavaScript setting to your configuration to load your own stylesheets in addition to Janrain’s default stylesheets:

janrain.settings.capture.stylesheets = ['styles/my-styles.css'];

Note that the stylesheets setting accepts an array of parameters, so it is possible to specify more than one stylesheet.

Additionally, note that the Registration UI generates some inline styles. You can disable this behavior by enabling the noModalBorderInlineCss setting:

janrain.settings.capture.noModalBorderInlineCss = true;

If you wish to completely override the styling of the Registration UI with your own stylesheets (not load Janrain’s at all), you can enable the noStyling setting:

janrain.settings.capture.noStyling = true;

However, in cases where you wish to drastically re-style and customize the Registration UI it often makes more sense to implement an API-Only version of registration.

How do I add mobile-specific stylesheets?

If the Registration UI detects that an user is visiting your page via a mobile device, then it will load mobile stylsheets. To load your own custom mobile stylesheets, modify this JavaScript setting:

janrain.settings.capture.mobileStylesheets = ['styles/my-mobile-styles.css'];

Note that the mobileStylesheets setting accepts an array of parameters, so it is possible to specify more than one stylesheet.

How do I load IE-specific stylesheets?

If the Registration UI detects the user is visiting the page via Internet Explorer, it can be configured to load stylesheets conditionally for IE8 and below:

janrain.settings.capture.conditionalIEStylesheets = ['ie6.css', 'ie7.css'];

Note that the this setting accepts an array of parameters, so it is possible to specify more than one stylesheet.

What are Janrain’s major DOM elements?

This table summarizes the major DOM elements/containers, with respect to styling. Other/minor DOM elements are discoverable on the standard reference implementation markup. Field elements are given element ids of the form 'capture_'+screenname+'_'+fieldname.

Element Description
#janrainModal General container for the UI
#janrainModalOverlay Background for the UI that pops up only when the janrain.capture.ui.modal.open(); function is called
#returnSocial The main body of the UI when a user who is already signed in returns to the site (i.e. when a "Welcome back"-style message is displayed)
.capture_header The main header of the UI (i.e. "Sign In Here")
.janrain_modal_closebutton The X-shaped button in the upper right-hand corner of the UI, used to close the UI
#janrainEngageEmbed This is the element that houses your social login UI. It houses the login buttons
#janrainProviderPages This element houses the social login buttons for the identity providers that you have chosen
.janrain-capture-ui-mobile Class appended to all screens on mobile devices.
.janrain-capture-ui-mobile-portrait Class based on portrait orientation of device.
.janrain-capture-ui-mobile-landscape Class based on landscape orientation of device.

How do I modify modal borders?

The most important thing to note when customizing your UI borders is that there is a distinction between the Social Login functionality and the Registration functionality. The difference is that Social Login houses your login buttons (e.g. buttons housing the names and logos of the identity providers you have chosen), whereas the Registration comprises the whole UI (of which Social Login is a part).

Modifying the border of your Social Login UI (i.e. the inner UI) can be done via the janrain.settings object. Setting the border color to a bright red would be done like this:

    janrain.settings.borderColor = '#EB0C0C';

Note: You must enter a hexadecimal color value for a color, or else your UI will throw JavaScript errors.

Here’s how to change the border’s radius (thickness) to 5 pixels:

    janrain.settings.borderRadius = 5;

Note: The borderRadius attribute is always expressed in pixels (px in CSS) and carries a maximum value of 10. In addition, you may set the borderWidth value in an analogous fashion.

Altering the border of your Registration modal—the outer shell of the UI—involves one initial step: you must turn on inline CSS within the JavaScript, which enables you to set those values yourself:

    janrain.settings.capture.noModalBorderInlineCss = false;

Once you have done that, you can change the border’s properties via the janrain.settings.capture object. Here’s how to set the border width to 10 pixels:

    janrain.settings.capture.modalBorderWidth = 10;

Note: This value is expressed in pixels, and carries a maximum value of 20.

Here’s how to set the border’s color to charcoal gray:

    janrain.settings.capture.borderColor = '#424242';

Customizing Transactional Emails

How do I add or remove an email?

Adding or removing email templates is not supported in the Configuration API. Please contact your Janrain representative if you have additional questions.

How do I configure the sender address for transactional emails?

You may provide a custom sender email address from which any transactional emails will be sent to users. The default email sender if not customized is noreply@janrain.com.

You will need to complete a verification process to allow a new email address to be used by our Amazon SES service. The email address needs to be set up as a valid email address that will accept emails at least temporarily.

Janrain will request an Amazon-generated email to be sent to the address with a verification link that must be clicked within 24 hours. We will confirm with you when the verification email is generated, so if you do not see it immediately be sure to check if the email has been marked as SPAM. Once you have validated the email, you can disable the acceptance of emails if you choose.

Once that is complete, then you can add the email_sender_address setting to your API clients where you wish to use the sender address.

How can I send transactional emails through a third-party rather than Janrain?

Janrain has a pre-built integration with Salesforce Marketing Cloud that may be used to send transactional emails. Talk to your Janrain representative about how this integration may be configured for your solution.

Customers who wish to leverage their existing Email Service Provider (ESP) for implementing transactional email maydo so by following the steps below.

Note: This assumes the ESP provides a mechanism for triggering emails via API.

  1. Identify the events that should trigger an email. See the Default Registration Experience Emails section above for the transactional emails that Janrain provides for a standard implementation.

  2. Add a handler to the Janrain onCaptureSaveSuccess JavaScript event to collect the form that was submitted and the email address that was input and send this data to your email service. For example, to send a confirmation email after registration, your event handler would look something like this:

  janrain.events.onCaptureSaveSuccess.addHandler(function(result){
    if (result.form == "registrationForm") {
      var email = document.getElementById("capture_traditionalRegistration_emailAddress").value;
      // send "email" to your service and specify what email template to send
    }
  }
  1. If you wish to send an email when a user changes their email address, password, or another profile attribute, then Janrain will need to activate a webhook to notify you when the relevant attributes change for a user record. Janrain will need to know the URL of the service that will receive the webhook notification.

  2. Create an email service to run on your web server or other web accessible location. The service should support the following functions:

    1. Process requests from the JS event handler to send emails.

    2. Process requests from the Janrain webhook service, if applicable, to send emails.

    3. Retrieve additional profile data using the /entity API needed for inclusion in the email content. For example, the user’s first name for the email salutation.

    4. Construct password reset URL by retrieving an authorization code using the /access/getAuthorizationCode API. Please note the following guidelines when making this call:

    5. The default expiration time for authorization codes is 30 seconds. To set the length of time that codes generated for password reset links are valid, include the time in seconds in the lifetime parameter of this call.

    6. The API client that is used to generate an authorization code must be the same as the API client that will be used to consume the code on your password reset page. Use the for_client_id parameter to specify which API client will be used to consume the code.

    7. The redirect_uri parameter must also match the value configured for the password_recover_url setting for the API client used to make this call.

    8. Once you have generated a code, append it to your password reset link with ?code=<Generated Code>.

    9. Construct email verification URL by retrieving a verification code using the /access/getVerificationCode API. Please note the following guidelines when making this call:

    10. The default expiration time for verification codes is 7 days. To set the length of time that codes generated for email verification links are valid, include the time in seconds in the lifetime parameter of this call.

    11. The attribute_name parameter is used to specify what attribute will be updated with the current timestamp when the verification code is consumed, usually emailVerified.

  3. Initiate email sends with your ESP with the following details:

    • Recipient’s email address
    • Sender’s email address (optional)
    • What email to send
    • Password reset or email verification URL (required depending on email type)
  4. Disable Amazon SES emails in the Capture dashboard:

    • To disable emails application wide, change the email_method setting under the Default Settings to disabled.
    • To disable emails for particular API clients, add a new client setting called email_method and set it to disabled.

Customizing language/locale

What elements are localized?

Generally speaking, Fields and i18nStrings (“access denied” messages, for example) are localized. However, any markup besides the field JTL tags are not localized.

If you wish to add localized strings to your registration experience that aren’t input elements (for instance, localizing the text of the submit button), you can utilize the /config/{app}/Flows/{Flow}/strings endpoints to add additional localized strings to your Flow.

How do I see all localized strings in my flow?

If you wish to see all strings that are localized in your Flow, make a GET call the the /config/{app}/Flows/{Flow}/translations endpoint.

You can receive your translations encoded in either CSV or JSON format, however we recommend using CSV format because it can be directly edited by a spreadsheet program. To do this, set the Accept header to “text/csv” in your request. Below is an example csv-formatted response:

path,key,en-US
fields.someField.label,6b233d297b11ee86e054bea7c381610d,Register
fields.anotherField.label,61dcb42842469f0f198aea9d809176d0,Hello!
fields.oneMoreField.label,5992bf1a97a97e36c18b3aa1459efda7,Goodbye
...

Caution: Do not remove any of the existing columns, such as path or key; these are required by the Flow. The path key corresponds to a field or i18nString path/name, and the key provides a unique identifier that is utilized in the field and i18nString definitions.

How can I load the Registration UI in different languages?

To view your Registration UI in a different localization, there are two javascript settings that should be enabled:

janrain.settings.language = 'fr-FR';
janrain.settings.capture.language = 'fr-FR';

There is an important distinction between these two settings. The janrain.settings.language setting controls localization for the Social Login Registration UI, and only a limited set of languages are supported .

On the other hand, the janrain.settings.capture.language setting specifies the locale of elements defined in the Flow translations, which are not constrained to a specific set of locales. You can add or update new translations via the Configuration API.

How do I add a new language/locale to registration?

To add a new language/locale to your registration, you need to make configuration changes via the configuration API.

  1. GET your current translations.

  2. Add the new locale to your current translations by adding a new column for the new locale and name it in the header row; in the example below, the “fr-FR” locale has been added to the CSV file:

    path,key,en-US,fr-FR
    fields.someField.label,6b233d297b11ee86e054bea7c381610d,Register,Faire inscrire
    fields.anotherField.label,61dcb42842469f0f198aea9d809176d0,Hello!,Bonjour!
    fields.oneMoreField.label,5992bf1a97a97e36c18b3aa1459efda7,Goodbye,Au revoir!
    ...
    
  3. Upload your new translations by making a PATCH request to the /config/{app}/Flows/{Flow}/translations endpoint. PATCH the updated file into the Flow specifying the content type as text/csv.

To view the updated translations, set the locale of the Registration UI by updating the language setting:

janrain.settings.language = 'fr-FR';

How do I modify the translations for an existing locale?

You can follow the same set of steps as described in the section on how to add a locale, with one modification: instead of adding a new locale to the translations file, you can simply modify the translations as-is.

For instance, if your translations are currently:

path,key,en-US
fields.someField.label,6b233d297b11ee86e054bea7c381610d,Register
fields.anotherField.label,61dcb42842469f0f198aea9d809176d0,Hello!
fields.oneMoreField.label,5992bf1a97a97e36c18b3aa1459efda7,Goodbye
...

You can modify them like so, and make a PATCH request with the modified file:

path,key,en-US
fields.someField.label,6b233d297b11ee86e054bea7c381610d,Join Us
fields.anotherField.label,61dcb42842469f0f198aea9d809176d0,Good day!
fields.oneMoreField.label,5992bf1a97a97e36c18b3aa1459efda7,See you later
...

Managing Multiple Sites and Brands

By default, the standard registration experience includes the standard Flow and user entityType, and for most cases this suffices. However, when managing the complexity that comes hand-in-hand with multiple brands, sometimes it is necessary to implement additional Flows and entityTypes.

When should I create multiple flows?

If one of the below scenarios applies to your brand/site, then you may want to consider creating another copy of your Flow:

  • Brand A requires pieces of information that should be optional for Brand B
  • Your sites/brands are very different aesthetically, and you use Janrain’s transactional emails

You can copy a Flow by making a POST request to the /config/{app}/Flows/{Flow}/copy Configuration API endpoint. Then, you can reference this new Flow at your site via the flowName and flowVersion settings:

janrain.settings.capture.flowName = "myNewFlow";
janrain.settings.capture.flowVersion = "01234567890123456789";

The following subsections describe the above use cases in more detail.

Brand A requires pieces of information that should be optional for Brand B

Suppose you have site A and site B. Site A requires birthdate, but site B does not. Suppose that, in order to fulfill the requirements of site A, you have created a birthday field that has the required validation rule.

At first consideration, in order to fulfill the requirements of site B it may seem like a good idea to create another birthday field that doesn’t have the required validation rule (let’s call this field “birthdayOptional”), and then to exclude the required birthdate field on site B.

Unfortunately, this would not work. Although Site A uses the “birthday” field and site B uses the “birthdayOptional” field, both sites use the same registration form in the Flow. Therefore, while site B may exclude the JTL tag markup on the registration screen for the required version of the birthday field, the registration form in the Flow still expects this field to be submitted to it. Since this “birthday” field has the required validation rule, then registration will always fail with validation errors on site B.

One alternative may be to make both fields optional, and then to implement your own client-side JavaScript validation on site A where birthday is required. However, this approach excludes server-side validation (not a recommended practice). Therefore, it is better in these cases to create a copy of your existing Flow, add/remove/modify fields on the new Flow, and then direct each site to the respective Flow.

Your sites/brands are very different aesthetically, and you use Janrain’s transactional emails

A single Flow assumes the same general look and feel for email templates across all sites–for instance, maybe the registration confirmation email has a 3-column horizontal layout with a title and body. The email template then may include JTL tags that allow variation in images, welcome messages, or values for style elements in order to give each site a different feel/appearance.

However, what if you want to have a registration confirmation email for Site A that has a 3-column layout, but for Site B you want to have a single-column layout?

Since a single Flow only allows only one template across sites for each transactional email type, then both sites would need to share the same template. At first glance, putting HTML into API client settings and then referencing those in your emails may seem like a feasible solution. However, this approach is not recommended; API client settings values are escaped and printed as plain text.

Therefore, if you wish to achieve dramatically different email template layouts for each site the best approach is to create a copy of your Flow and modify the email templates in the new Flow.

Alternatively, also considering utilizing third-party email integrations if your transactional email solution requires a high degree of customization.

Why might I implement multiple entityTypes?

If one of the below scenarios applies to your sites/brands, then you may want to consider creating a new entityType:

  • Sites A and B are two drastically different brands; it would be too complex to incorporate all brand structures into one schema for user profile data
  • You wish to segment users from Site A and users from Site B and therefore cannot have data in common between the two sites
  • You do not want your users to view brands as associated with each other; for instance, sharing the same login experience between child and adult brands.
  • Site A has special membership validations and users from siteB shouldn’t be able to login with their profile from siteB. A common example is meeting legal agreements for doctor-login portals between countries.

Generally speaking, To implement multiple entityTypes, you need to change both the Flow and the API client settings in the dashboard, in addition to creating your new entityType.

  1. Create your new entityType by making a POST call to the /entityType.create Capture endpoint. If you want to copy an existing entity and modify it, you can do this by copying the attr_defs object from a GET request on the desired entityType. You must not include the id or uuid attributes, as these are automatically created with the new entityType. Below is an example value for the attr_defs URL parameter, which creates an entityType with the “name” and “description” attributes.

    [
      {
        "name":"name",
        "type":"string",
        "case-sensitive":false
      },
      {
        "name":"description",
        "type":"string",
        "length": 1000,
        "case-sensitive":false
      }
    ]
    
  2. In the Flow, add the list of entityTypes to the schemas object in the Flow. Below is an example PUT request adding the entityType user_2 to the Flow. Note, make sure to include in your request all entityTypes that this flow may be used with, not just the entityType you wish to add.

    {
      "userData": [
        "email",
        "displayName"
      ],
      "schemas": [
        "user",
        "user_2"
      ]
    }
    
  3. In your API client settings add the user_entity_type setting to all clients to specify the entityType each uses.

    Adding the user_entity_type to the dashboard