**Source URL:** https://general.veevavault.dev/clinical/custom-pages/guides/data-management.md

# Managing Data Flow

The [`@veeva/vault` JavaScript package](/custom-pages/vault-web-sdk) allows you to send and receive data from `PageController`.

From your client code, you can:

* [Retrieve data](#Loading_Server_Data) from the server when a user loads your Custom Page in Vault

* [Trigger a page reload](#Reloading_the_Page)

* [Send an event](#Sending_Events) with data to the server and handle the returned data

* [Send a request](#Using_API) to Vault API

The `definePage()` function provides these key parameters for data management:

| Parameter | Description |
| --- | --- |
| `data` | Data returned from `PageController`'s `onLoad()` response |
| `element` | Root HTML element to append to when writing client code |
| `pageContext` | Page context providing the `reload()` function |
| `sendEvent` | Function to send an event to the `PageController` |

## Loading Server Data {#Loading_Server_Data}

Loading your Custom Page in the browser calls the `PageController`’s [`onLoad()`](/custom-pages/guides/developing-server-code/#onLoad) method. In the client code, the `data` parameter provides the data returned from the `onLoad()` method.

For example, if the `PageController`’s `onLoad()` method returns the `userId` of the currently authenticated user, you can get the user ID from the `data` parameter and display it on the page:

```
import React from 'react';
import { createRoot } from 'react-dom/client';
import { definePage } from '@veeva/vault';

export default definePage(({ data = {}, element }) => {
    const { userId = '<userId>' } = data;
    const root = createRoot(element);
    root.render(
        <div>Hello user {userId}!</div>
    );
});

```

## Reloading the Page {#Reloading_the_Page}

You can trigger a page reload from the client using the `pageContext` parameter’s `reload()` function. This function calls the `PageController`’s [`onLoad()`](/custom-pages/guides/developing-server-code/#onLoad) method.

```
export default definePage(({ element, pageContext }) => {
...
        <button onClick={() => pageContext.reload()} >Refresh</button>
...

```

## Sending Events {#Sending_Events}

From the client code, use `sendEvent()` to send an event with data to the `PageController`. This calls the `PageController`’s [`onEvent()`](/custom-pages/guides/developing-server-code/#onEvent) method, which processes the data and returns it as a JSON response.

```
export default definePage(({ element, sendEvent }) => {
...
async function fetchData() {
	const serverResponse = await sendEvent("myEvent", requestData);
...

```

<Aside type="note">You can queue up to 50 events in the client code for processing.</Aside>

## Using Vault API {#Using_API}

You can use [Vault API](/vault-api/api-reference) directly from your client code by importing the `vaultApiClient`. You can retrieve Vault data using the `vaultApiClient.fetch()` async function:

```
import { vaultApiClient } from "@veeva/vault";
...
  async function fetchDocuments() {
      vaultApiClient.fetch('/v25.1/objects/documents', {
        headers: {
          "X-VaultAPI-ClientID": "hello-world",
          "Content-Type": "application/json",
        },
      })
        .then(...);
...

```

Vault automatically uses the host name of the currently authenticated Vault and appends the `/api` suffix.

We recommend setting a unique `X-VaultAPI-ClientID` header value to track in the API Usage Logs.

API calls made from Custom Pages count towards [API rate limits](/vault-api/references/api-rate-limits) and are filtered with [Client ID Filtering](/vault-api/references/client-id/#Client_ID_Filtering).

Users do not need API permission to view a Custom Page that calls Vault API from code.

## Controlling Navigation {#Controlling_Navigation}

Custom Pages can control navigation and history from client code using custom URLs to Vault locations and the `vaultLocation` and `history` objects. For example, this allows you to add breadcrumb links or a custom Back button to a Custom Page.

### Retrieving Server-Generated URLs {#retrieving-server-generated-urls}

Access `UrlService` URLs using the `data` parameter in your client code. The server code must add URLs to the response to make them available to the client code.

In the following example, the server code has added the `urls` array to the response data. The client code can access this data using `data.urls`, as in the following example:

```
import { definePage } from '@veeva/vault';

export default definePage(({ element, data }) => {
  element.innerHTML = `
    <div>
      <h1>Vault Location URLs</h1>
      <div>
        <ul>
          ${data?.urls?.map(url => `<li><a href="${url}">${url}</a></li>`).join('') ?? ''}
        </ul>
      </div>
    </div>
`;

```

### Location & History {#Location_History}

The `window.vaultLocation` object allows access to the browser’s `location` object in Vault.

The browser’s `window.history` object is also available in Vault and allows navigation through a user’s session history. Note that the `history.pushState()` and `history.replaceState()` functions are not available.

<Aside type="note">When using Typescript, you can type `window.vaultLocation` and set `location` in the local scope as follows:

```
const location = (window as typeof window & { vaultLocation: Location }).vaultLocation;

```
</Aside>
The following example creates a Custom Page with a button that navigates to the previous page and buttons that set and display the current browser location. The server code has set `homeUrl` with a single URL string, and the second button sets the current location to that URL via `data.homeUrl`.

```
import { definePage } from '@veeva/vault'; 

export default definePage(({ element, data }) => { 
  element.innerHTML = ` 
    <div>
      <h1>Custom Page</h1> 
      <h2>Navigation Buttons</h2> 
      <button id="historyBack">Back</button> 
      <button id="setLocation">Set location</button> 
      <button id="locationHref">Get location</button>
    </div>
  `;

  element.querySelector('#historyBack').onclick = () => { 
    history.back();
  };
  element.querySelector('#setLocation').onclick = () => { 
    vaultLocation.href = data.homeUrl;
  };
  element.querySelector('#locationHref').onclick = () => { 
    alert(vaultLocation.href);
  };
});

```


---

**Previous:** [Developing Server Code](/clinical/custom-pages/guides/developing-server-code)  
**Next:** [Configuring Custom Pages](/clinical/custom-pages/guides/page-configuration)