# Create a Headless Registration Handler

Create an Apex class for your registration handler. You reference this Apex class when you configure Experience Cloud settings on the Login & Registration page.

| Required Editions                                                                          |
| ------------------------------------------------------------------------------------------ |
| Available in: both Salesforce Classic (not available in all orgs) and Lightning Experience |
| Available in: **Enterprise**, **Unlimited**, and **Developer** Editions                    |

1. From Setup, in the Quick Find box, enter `Apex`, and then select **Apex Classes**.

2. Click **New**.

3. Fill the class with your headless registration handler code. You can paste in the code from the example.

4. Save the class, and note its name.

## Example

Here’s an example headless registration handler. This registration handler creates a user and links it to the account and profile that you created earlier in this guide.

:::note
This sample code is for demonstration only. Always test code before deploying it to a production environment.
:::

```nolang
/*
 * Sample Headless Self Registration Handler class for Headless Identity implementation
 */

global class HeadlessSelfRegistrationHandler implements Auth.HeadlessSelfRegistrationHandler{
    static final String headless_account = 'My Account';
    
    // Creates a Standard salesforce or a community user
    global User createUser(Id profileId, Auth.UserData data, String customUserDataMap, String experienceId, String password){
        User u = new User();
        //Ensures the user will save as all required fields are pre-filled in with dummy values
        prepareUserData(data, u);

        //Get the Account, and create it if one is not already present. 
        Account a;
        List<Account> accounts = [SELECT Id FROM Account WHERE name='My Account'];
        if(accounts.isEmpty()) {
            a = new Account(name = headless_account);
            insert(a);
        } else {
            a = accounts[0];
        }
        
        handleCustomData(customUserDataMap); 
        
        // Create the Contact
        Contact c = new Contact();
        c.accountId = a.Id;
        c.firstName = u.firstName;
        c.lastName = u.lastName;
        insert(c);
        
        //Associate the Contact to the user along with the profile. 
        u.profileId = profileId;
        u.contactId = c.Id;
        return u;
    }
    
    /*
     * We support the ability to pass in complex structures in the custom user data map
     * You can build Apex classes that represent your complex structure
     * Then deserialize that structure into your Apex class
     * In this case we have a class at the bottom of this file called "ContactInformation"
     * This class deserializes the incoming request and prints out the fields
     * */ 
    void handleCustomData(String customUserDataMap) {
        System.debug('Custom Data: ' + customUserDataMap); 
        ContactInformation contactInfo = null; 
        try {
            contactInfo = (HeadlessSelfRegistrationHandler.ContactInformation)JSON.deserialize(customUserDataMap, HeadlessSelfRegistrationHandler.ContactInformation.class);
            System.debug('ContactInfo.mobilePhone: ' + contactInfo.mobilePhone); 
            System.debug('ContactInfo.streetAddress: ' + contactInfo.streetAddress); 
            System.debug('ContactInfo.city: ' + contactInfo.city); 
            System.debug('ContactInfo.state: ' + contactInfo.state); 
        } catch (Exception e) {
            System.debug('JSON was not formed correctly for the apex class'); 
        }
        
        
    }
    
    /*
	* This method handles filling user data that is required by Salesforce but is not passed in during registration
    * It is not strictly necessary but helpful as it centralizes the management of unnecessary fields to the IDP instead of the client. 
	*/
    void prepareUserData(Auth.UserData data, User u){
        
        String name, firstName, lastName, username, alias, email;
        
        System.debug('----> Passed In User Information');
        System.debug('Email: ' + data.email);
        System.debug('First Name: ' + data.firstName);
        System.debug('Last Name: ' + data.lastName);
        
        for(String key : data.attributeMap.keySet())
        {
            System.debug('key: ' + key + ' value: ' + data.attributeMap.get(key));
        }
        // Initialize the attributes required to create a new user with dummy values
        // in case they are not provided by the Auth Provider
        firstName = 'change-me';
        lastName = 'change-me';
        email = 'change@me.com';
        if(data.email != null && data.email != '')
            email = data.email;
        if(data.firstName != null && data.firstName != '')
            firstName = data.firstName;
        if(data.LastName != null && data.lastName != '')
            lastName = data.lastName;
        if(data.attributeMap.containsKey('full_name'))
            name = data.attributeMap.get('full_name');
        if(data.attributeMap.containsKey('name'))
            name = data.attributeMap.get('name');
        if(firstName == 'change-me' && name != '')
            firstName = name.substringBefore(' ');
        if(lastName == 'change-me' && name.substringAfter(' ') != '')
            lastName = name.substringAfter(' ');
        
        // Generate a random username
        Integer rand = Math.round(Math.random()*100000000);
        if(data.attributeMap.containsKey('username')){
            username = data.attributeMap.get('username');
        }else{
            username = lastName + '.' + rand + '@social-sign-on.com';
        }
        alias = firstName;
        
        //Alias must be 8 characters or less
        if(alias.length() > 8)
            alias = alias.substring(0, 8);
        u.username = username;
        u.email = email;
        u.lastName = lastName;
        u.firstName = firstName;
        u.alias = alias;
        u.languagelocalekey = UserInfo.getLocale();
        u.localesidkey = UserInfo.getLocale();
        u.emailEncodingKey = 'UTF-8';
        u.timeZoneSidKey = 'America/Los_Angeles';
    }
    
    /*
     * Apex Class Representation of Contact Information 
     * which was passed in the custom data map
     * */ 
    global class ContactInformation {
        String mobilePhone;
        String streetAddress;
        String city; 
        String state;
        Boolean privacyPolicy; 
    }
}
```
