# End User-defined schema

Here we take you through data mapping use cases where the End User configures the mapping for their solution instance

## Overview

Here we take you through data mapping use cases where the End User configures the mapping for their solution instance.

## 1. Hardcoded list + allow custom values

There may be some cases where it is too restrictive for your End Users to only be able to choose from a pre-configured list of fields.
For example, your End Users might be using different MySQL database tables with different field names and you want them to be able to name the fields to be mapped to themselves.
One End User may wish to set up the following mapping:

| Service 1 | Service 2      |
| --------- | -------------- |
| name      | account\_name  |
| id        | stripe\_id     |
| phone     | cellphone      |
| email     | email\_address |

While another may wish to set up the following mapping:

| Service 1 | Service 2      |
| --------- | -------------- |
| name      | customer\_name |
| id        | id             |
| phone     | mobile         |
| email     | email          |

To do this you can follow the usual procedure for data mapping, as outlined in the Hardcoded Example.

### Config wizard steps

Then, when editing the Config Wizard in the Solution Editor, you can:

### Tick the Allow custom values box

![allow-custom-values](https://tray.ai/documentation/images/platform/embedded/advanced-features/data-mapping/end-user-defined-schema/1e6c9118-3f2c0f44_allow-custom-values.png)

### End-user experience: Custom values

### End user experience

This allows the End User to then manually enter the values they wish
![enter-custom-mapping-values](https://tray.ai/documentation/images/platform/embedded/advanced-features/data-mapping/end-user-defined-schema/1e6c9118-2409e5f1_enter-custom-mapping-values.png)

## 2. Using input and output schema

> **Info:** Before continuing to the instructions below, note that picking fields from drop-downs which come from the auto-generated connector schemas is in theory an easy and simple method. However, it will not always be possible to use the input and output schema of connectors, as sometimes they will not produce fields you are trying to get to which may be one or two layers deep into the schema (e.g. the name of an assignee for an Asana task may be found in `$.steps.asana-1.data.assignee.name`).

If this is the case you should hardcode your lists and extract the nested data.
The example from the previous pages on hardcoding and mapping nested data is a good illustration, in that the Output schema for the Stripe 'List Customers' operation only shows the top-level 'Data' field and cannot drill down into id, name, currency etc.:
![stripe-output-schema](https://tray.ai/documentation/images/platform/embedded/advanced-features/data-mapping/end-user-defined-schema/d8b51179-372b452f_stripe-output-schema.png)
A very simple (and unrealistic!) example of using input/output schema is setting up a mapping for a workflow whereby each time a new Slack channel is created a Dropbox folder is created with the name of the channel mapped to the name of the folder.
So here you could use the following setup:

### Operation Input in Service 1:

![service-1-slack-setup](https://tray.ai/documentation/images/platform/embedded/advanced-features/data-mapping/end-user-defined-schema/d8b51179-c72ed6e0_service-1-slack-setup.png)

### Operation Input in Service 2:

![service-2-dropbox-setup](https://tray.ai/documentation/images/platform/embedded/advanced-features/data-mapping/end-user-defined-schema/d8b51179-063142dd_service-2-dropbox-setup.png)

### Default mapping:

![slack-dropbox-default-mapping](https://tray.ai/documentation/images/platform/embedded/advanced-features/data-mapping/end-user-defined-schema/d8b51179-64ee5b95_slack-dropbox-default-mapping.png)

In deciding whether to use an input or an output schema for a particular operation, it will depend on what data is returned by either schema, and whether it is usable.
In the example above we could have used the output schema for the Slack 'Create channel' operation but this only returns the 'Channel' as an object, and the name is nested within it.
So using the input schema was necessary.
If you need to create a more detailed mapping with some of the nested data from within the channel object, you would need to use the hardcoded example with nested values approach detailed in the Mapping Nested Data guide (making use of Object Helpers).

## 3. Using Dynamic Lookup Schema

An example of when you might use this is if the operation you are mapping to has multiple types, and the required data will change depending on the type.
Dynamic lookup can also be used as an alternative to hardcoding when you need to get at nested values.
The Salesforce 'Create record' operation is a good example. In the hardcoded example we use it to create an Account, but you might also want your End User to be able to choose which type of record gets created - it could be a Lead or a Contact.
In this case, your End User would be able to choose from a type drop-down in the Config Wizard:
![choose-record-type](https://tray.ai/documentation/images/platform/embedded/advanced-features/data-mapping/end-user-defined-schema/307a633d-e422b739_choose-record-type.png)
The available fields then change depending on whether they choose

### 'Account':

![sf-account-available-fields](https://tray.ai/documentation/images/platform/embedded/advanced-features/data-mapping/end-user-defined-schema/307a633d-930c5909_sf-account-available-fields.png)

### Or 'Lead':

![sf-lead-available-fields](https://tray.ai/documentation/images/platform/embedded/advanced-features/data-mapping/end-user-defined-schema/307a633d-635ede74_sf-lead-available-fields-2.png)

### Or 'Contact':

![sf-contact-available-fields](https://tray.ai/documentation/images/platform/embedded/advanced-features/data-mapping/end-user-defined-schema/307a633d-2f14fd2b_sf-contact-available-fields.png)

### Setting up a dynamic lookup

### Setting up a Dynamic Lookup

In the above example we first of all had to make sure that there was a Config value set for **recordType** in the source workflow:
![config-in-source-workflow](https://tray.ai/documentation/images/platform/embedded/advanced-features/data-mapping/end-user-defined-schema/307a633d-42eb18ae_config-in-source-workflow.png)
This can be made available in the first screen of the Solution Editor. Note that because the config was set in the **Record Type** drop-down in the source workflow, the system has picked up that it is a DDL, and so will present the End User with the drop-down list of record types, as per the first screenshot at the top of this page:
![recordtype-solution-editor](https://tray.ai/documentation/images/platform/embedded/advanced-features/data-mapping/end-user-defined-schema/307a633d-243c0265_recordtype-solution-editor.png)
Then when setting up the data mappings, having selected 'Dynamic lookup' as the method and Salesforce as the service, we then choose **Find Records** as the operation:
![sf-dynamic-lookup-settings](https://tray.ai/documentation/images/platform/embedded/advanced-features/data-mapping/end-user-defined-schema/307a633d-ebf49bc8_sf-dynamic-lookup-settings.png)
For **Which auth slot do you want to use for the DDL call?** we choose the auth slot that was made when authenticating Salesforce in the source workflow (this will be automatically available)
For **Which DDL lookup do you want to use?** we can choose the 'private\_list\_object\_fields' lookup, which will pull the available fields for the record type chosen. Note that only certain connectors will have operations like this available.
Of key importance here is **Which config slot does the operation depend upon?.** Here we set it depend on the **recordType** which we allowed the End User to select in the first screen.

### Allowing users to enter custom values

### Allowing users to enter custom values

When presenting users with drop-down lists it is also possible to allow them to enter an arbitrary custom value in a drop-down list, instead of choosing from one of the options:
![custom-val-in-field-list-ddl](https://tray.ai/documentation/images/platform/embedded/advanced-features/data-mapping/end-user-defined-schema/307a633d-0605c5a7_custom-val-in-field-list-ddl.gif)
This is done by ticking the **Allow custom values** box:
![dynamic-lookup-allow-custom-values](https://tray.ai/documentation/images/platform/embedded/advanced-features/data-mapping/end-user-defined-schema/307a633d-a9502592_dynamic-lookup-allow-custom-values.png)
Note that this is turned off by default as, with some service operations, it can cause errors by allowing users to enter invalid values.

## 4. Using Config Slots

To do this you can follow the usual procedure for data mapping, as outlined in the Hardcoded Example.
The extra key steps are:

### 1. Add an extra config data variable to your mapping script:

This should be called something similar to **userMappings**:
![add-user-mappings-variable](https://tray.ai/documentation/images/platform/embedded/advanced-features/data-mapping/end-user-defined-schema/070a5dbd-8b3e9857_add-user-mappings-variable.png)
And it should be an array:
![user-mappings-set-as-array](https://tray.ai/documentation/images/platform/embedded/advanced-features/data-mapping/end-user-defined-schema/070a5dbd-1e36def6_user-mappings-set-as-array.png)

> **Warning:** **IMPORTANT!**: You do not need to adjust the actual mapping script.

### 2. Set the user mappings variable screen in the Solution Editor

You will need the End User to set the available fields *before* the actual mappings:
![solution-editor-set-user-mappings=screen](https://tray.ai/documentation/images/platform/embedded/advanced-features/data-mapping/end-user-defined-schema/070a5dbd-b911f46d_solution-editor-set-user-mappings=screen.png)

### 3. Set the appropriate data mapping service to use the config slot

To extend the Stripe use case from the [Hardcoded Example](https://tray.ai/documentation/platform/embedded/advanced-features/data-mapping/tray-partner-defined-schema) we can leave the first service as is:
![config-slots-service-1-fields](https://tray.ai/documentation/images/platform/embedded/advanced-features/data-mapping/end-user-defined-schema/070a5dbd-d2789ae5_config-slots-service-1-fields.png)
But then for service 2 we can specify that it uses the **userMappings** config slot:
![config-slots-service-2-fields](https://tray.ai/documentation/images/platform/embedded/advanced-features/data-mapping/end-user-defined-schema/070a5dbd-8708b7db_config-slots-service-2-fields.png)

### End User experience: Config slots

### End user experience

When an End User runs the Config Wizard they can, first of all, add a list of fields for the service to be mapped to:
![config-wizard-set-user-mappings](https://tray.ai/documentation/images/platform/embedded/advanced-features/data-mapping/end-user-defined-schema/070a5dbd-ed9371e3_config-wizard-set-user-mappings-3.png)
These fields will then be available when setting up the actual mappings:
![config-wizard-set-data-mappings-with-config-slots](https://tray.ai/documentation/images/platform/embedded/advanced-features/data-mapping/end-user-defined-schema/070a5dbd-bddd94f5_config-wizard-set-data-mappings-with-config-slots-2.png)
