> For the complete documentation index, see [llms.txt](https://docs.verygoodsecurity.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.verygoodsecurity.com/vault/developer-tools/vgs-collect/react-native-sdk/vgscollect.md).

# VGSCollect

The `VGSCollect` class is the main component of the VGS Collect SDK. It provides methods for registering fields, submitting data, and tokenizing data.

## Creating a VGSCollect

```javascript
/// Constructor.
///
/// - Parameters:
///   - id: your organization Vault id.
///   - environment: your organization vault environment with data region.(e.g. "live", "live-eu1", "sandbox").
 `VGSCollect(id: string, environment: string = 'sandbox')`
```

> * You can have multiple `VGSCollect` instances; they will work independently with the fields you configure for each specific instance.\
>   \- All `VGSCollect` instances can be configured differently.\\

The `VGSCollect` instance grabs the data from the `VGSTextInputs` during the `submit(_:)` request.

## Route Id

If you have multiple **Routes** in your organisation Vault, you can set required `routeId` for the VGSCollect instance. VGSCollect will send data to this specific Route in your Vault.

```javascript
/// - `routeId` (string): The vault route Id to set.
/// - Throws an error if the route Id is not a string.
setRouteId(routeId: string): void
```

## CNAME

When integrated with VGS, by default, the traffic is passed via the VGS proxy, which uses the `tntxxxxx.sandbox.verygoodproxy.com` format, where the `tntxxxxx` is your Vault identifier. The Collect SDK allows you to use your custom hostname and make requests to a non-VGS domain name.\
Before adding a new Hostname, you should create a CNAME record for your existing domain in your DNS provider’s account that points to `<VAULT_ID>.<ENVIRONMENT>.verygoodproxy.com`.

\*\* Learn more about [Custom Hostnames](/vault/http-proxy/inbound-connection/custom-hostnames.md)\*\*.

Then, in your Application, set the Custom Hostname in the `VGSCollect` instance:

```javascript
/// - `cname` (string): The CNAME to set.
/// - Returns a Promise that resolves when the CNAME validation is complete.
setCname(cname: string): Promise<void>
```

> • When the hostname is not valid or not registered in the VGS system, it will be ignored by the SDK and all traffic will be passed through the VGS proxy directly.\
> • Only **https** scheme is supported.\\

## Custom Headers

Set custom headers for the VGSCollect instance.

```javascript
setCustomHeaders(headers: Record<string, string>): void
```

## Code example

Full example of how to setup a card form with VGSCollect:

```javascript
// Setup your vauldId and environment
const collector = new VGSCollect('vaultId', 'sandbox');

const App = () => {
  // Store VGS input states
  const [formFieldsState, setFormFieldsState] = useState<{
    [key: string]: VGSTextInputState;
  }>({
    card_holder: { isValid: false } as VGSTextInputState,
    card_number: { isValid: false } as VGSTextInputState,
    expiration_date: { isValid: false } as VGSTextInputState,
    card_cvc: { isValid: false } as VGSTextInputState,
  });
  // Handle input state changes
  const handleFieldStateChange = (
    fieldName: string,
    state: VGSTextInputState
  ) => {
    console.log('> Field state changed:', fieldName, state);
    setFormFieldsState((prevState) => ({
      ...prevState,
      [fieldName]: state,
    }));
  };

  // Check if all fields are valid
  const areAllFieldsValid = () => {
    for (const fieldName in formFieldsState) {
      if (!formFieldsState[fieldName]?.isValid) {
        return false;
      }
    }
    return true;
  };

  // Handle submit request
  const handleSubmit = async () => {
    if (!areAllFieldsValid()) {
      return; // Prevent submission if any field is invalid
    }
    try {
      const { status, response } = await collector.submit('/post', 'POST');
      if (response.ok) {
        try {
          const responseBody = await response.json();
          const json = JSON.stringify(responseBody, null, 2);
          console.log('Success:', json);
        } catch (error) {
          console.warn(
            'Error parsing response body. Body can be empty or your <vaultId> is wrong!',
            error
          );
        }
      } else {
        console.warn(`Server responded with error: ${status}\n${response}`);
        if (status === 400) {
          console.error('Bad request! Check your VGSCollect config and input.');
        } else if (status === 500) {
          console.error('Server issue! Try again later.');
        }
      }
    } catch (error) {
      if (error instanceof VGSError) {
        switch (error.code) {
          case VGSErrorCode.InputDataIsNotValid:
            for (const fieldName in error.details) {
              console.error(
                `Not valid fieldName: ${fieldName}: ${error.details[fieldName].join(', ')}`
              );
            }
            break;
          default:
            console.error('VGSError:', error.code, error.message);
        }
      } else {
        console.error('Network or unexpected error:', error);
      }
    }
  };

  return (
    <SafeAreaView style={styles.safeArea}>
      <View style={styles.container}>
        <VGSTextInput
          collector={collector}
          fieldName="card_holder"
          type="cardHolderName"
          placeholder="Card Holder Name"
          onStateChange={(state: any) =>
            handleFieldStateChange('card_holder', state)
          }
          containerStyle={[
            styles.inputContainer, // Container-specific styles
            {
              borderColor: formFieldsState.card_holder?.isValid
                ? formFieldsState.card_holder?.isValid
                  ? 'green'
                  : 'red'
                : 'lightgrey',
            },
          ]}
          textStyle={[
            styles.inputText, // text-specific styles
          ]}
        />
        /// Add other VGS Inputs...
        </View>
        <TouchableOpacity
          style={[
            styles.button,
            { backgroundColor: areAllFieldsValid() ? 'blue' : 'gray' },
          ]}
          disabled={!areAllFieldsValid()}
          onPress={handleSubmit}
        >
          <Text style={{ color: 'white' }}>Submit</Text>
        </TouchableOpacity>
    </SafeAreaView>
  );
};

/// Set styles
const styles = StyleSheet.create({
  safeArea: {
    flex: 1,
    backgroundColor: 'white',
  },
  container: {
    flex: 1,
    paddingHorizontal: 20,
    paddingTop: 40,
  },
  inputContainer: {
    height: 50,
    borderWidth: 2,
    borderRadius: 8,
    paddingHorizontal: 12,
    backgroundColor: 'white',
    marginBottom: 20,
  },
  inputText: {
    fontSize: 16,
    color: 'black',
  },
  button: {
    backgroundColor: 'blue',
    padding: 15,
    borderRadius: 8,
    alignItems: 'center',
  },
});

export default App;
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.verygoodsecurity.com/vault/developer-tools/vgs-collect/react-native-sdk/vgscollect.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
