---
category: [Administration & Integrations, Platform and Product Extensions, Platform and Product Extensions/Integration, Administration & Integrations/Custom Integrations & Apps, Platform and Product Extensions/Workday Extend]
keyword: [Extend, Presentation Components, tags, UI components]
nav: wcp_docs
parent_url: /wcp_docs/
title: >- 
  Concept: Page Metadata
layout: subsection
---

A page consists of these main sections:

-   `presentation` - Defines the page layout and contains the page widgets.
-   `endPoints` - Contains inbound endpoints that fetch data.
-   `outboundData` - Contains outbound endpoints that update data, including outbound variables that other pages can reference.
-   `script` - Declares functions invoked by the page widgets.
-   `securityDomains` - Contains a list of security domains that grant or block access to a page. These security domains are model components within the app.


<b>Note:</b> A PMD file has a size limitation of 100 KB.

Refer to [Reference: Page Metadata](/wcp_docs/opb1667507816853.html) for a full list of root-level PMD properties.

## <a id="section_presentation"></a>Presentation

The `presentation` subschema of the PMD describes the page display and user interaction. Define the page widgets in the `presentation` subschema by using PMD tags. A PMD tag is a JSON tag definition containing attributes that customize the appearance and behavior of the widget. The PMD tag also enables you to bind its value to the data you want to display on the widget.

The `presentation` subschema contains:

-   `title` - The page header.
-   `body` - The root `section` of PMD tags. In the sample `workerProfile` PMD, the `body` contains these sample tags:

    -   welcomeMessage - A `text` tag that displays a static value.
    -   primaryInfo - A `fieldSet` that creates a subsection with a subtitle and 3 `text` tags. The sample text tags display data bindings from the `workerData` endpoint.
    -   contactInfo - A `button` that navigates to another page.

-   `footer` - The widgets at the bottom of the page.


```
{
  "id": "workerProfile",
  "presentation": {
    "title": {
      "type": "title",
      "label": "Worker Profile"
    },
    "body": {
      "type": "section",
      "horizontal": false,
      "children": [
        {
          "type": "text",
          "id": "welcomeMessage",
          "label": "Hello!",
          "value": "View your profile information."
        },
        {
          "type": "fieldSet",
          "id": "primaryInfo",
          "title": "Primary Information",
          "children": [
            {
              "type": "text",
              "id": "welcome",
              "label": "Name",
              "value": "<% workerData.descriptor %>"
            },
            {
              "type": "text",
              "id": "title",
              "label": "Business Title",
              "value": "<% workerData.businessTitle %>"
            },
            {
              "type": "text",
              "id": "location",
              "label": "Location",
              "value": "<% workerData.location.descriptor %>"
            }
          ]
        },
        {
          "type" : "button",
          "id": "contactInfo",
          "label" : "Contact Information",
          "action": "PRIMARY",
          "taskReference" : {
             "type" : "taskReference",
             "taskId" : "contactsPage"
          }
        }
      ]
    },
    "footer": {
      "type": "footer",
      "children": [
        {
          "type": "richText",
          "enabled": "false",
          "value": "Powered By Workday Extend"
        }
      ]
    }
  },
  "endPoints": [
    {
      "name": "workerData",
      "baseUrlType": "workday-common",
      "url": "/workers/me",
      "authType": "sso"
    }
  ]
}
```

The sample `workerProfile` PMD displays this page:

![](GUID-d221b36b-3d2b-44b6-8296-ce513f54bbdf-enHYPHENus.png)

## <a id="section_endpoints"></a>Endpoints

The `endPoints` subschema in the PMD declares how to fetch data from REST API endpoints that use the HTTP GET method. These endpoints, also known as inbound endpoints, fetch input data for the widgets to display. Assign a `name` to each endpoint so that the widgets can reference the endpoint and display the data it returns. The endpoints use a base URL, which you define as a data provider in the AMD.

This sample data provider in the AMD defines the base URL of the sample `workerData` endpoint:

```
{
      "key": "workday-staffing",
      "value": "https://api.workday.com/staffing/v1"
}
```

You can construct an endpoint by using a static URL path or by binding to dynamic values. The sample `workerData` endpoint uses the `/workers/me` URL path to fetch worker data for the current user:

```
  "endPoints": [
    {
      "name": "workerData",
      "baseUrlType": "workday-staffing",
      "url": "/workers/me",
      "authType": "sso"
    }
  ]
```

The fully constructed `workerData` endpoint is `GET https://api.workday.com/staffing/v1/workers/me`.

Instead of displaying worker data about the current user, this next example assumes that the sample `workerProfile` PMD displays data about a selected worker from another page. In a previous page, we determined the ID of the worker that the user selected, and saved it in `queryParams.id`. You can declare the same endpoint with a dynamic binding to the selected worker, using a parameterized URL. Example:

```
"endPoints":[
  {
    "name":"selectedWorkerData",
    "baseUrlType": "workday-staffing",
    "url":"<% '/workers/' + queryParams.id %>",
    "authType" : "sso"
  }
]
```

This endpoint constructs its URL by pulling in a value from the `queryParams` variable on the binding context. The `id` attribute contains the value you defined in the routing pattern of the task that launched this page. The fully constructed endpoint looks like `GET https://api.workday.com/staffing/v1/workers/3aa5550b7fe348b98d7b5`.

With endpoint names and dynamic binding, endpoints can refer to each other and the data that they retrieve. Dynamic binding to an endpoint can be useful if the request for a resource depends on the content of another.

You can also specify the authentication type for each endpoint.The default authentication is Single Sign-On (SSO).

<b>Note:</b> The maximum size of response data from an endpoint call is 25,000,000 bytes. If the size of the response data exceeds the maximum, Presentation Components:

-   Stop processing the response data beyond the maximum.
-   Write a `RestResponseTooLargeException` error on the Presentation Components log.
-   Return a page error with the internal server error 500.


## <a id="section_outboundData"></a>Outbound Data

The `outboundData` subschema in the PMD defines how you save the data entry on a page. When Presentation Components see the `outboundData` declaration on a page, it becomes an edit page and all widgets on the page take on their editable forms.

Outbound data consists mostly of outbound endpoints in the `outboundEndPoints` array. Like endpoints, outbound endpoints are declarations of REST API endpoints. However, unlike inbound endpoints, outbound endpoints only use HTTP methods that perform updates (POST, PUT, PATCH, DELETE).

```
"outboundData": {
    "outboundEndPoints": [
      {
        "name": "businessTitleChange",
        "baseUrlType": "workday-common",
        "url": "<% '/workers/' + queryParams.id + '/businessTitleChanges' %>",
        "httpMethod": "POST",
        "authType": "sso"
      }
    ],
    "responseErrorDetail":{
      "errorSummary":"<% error %>",
      "errors":"<% list:mapAttribute(errors, 'error') %>"
    }
  }
```

The sample `businessTitleChange` outbound endpoint uses the same `workday-common` defined in the AMD. The `url` declaration uses the dynamic binding with `queryParams` that takes the `id` of the selected worker. The fully constructed endpoint looks like `POST https://api.workday.com/staffing/v1/workers/3aa5550b7fe348b98d7b5/businessTitleChanges`.

The sample `businessTitleChange` outbound endpoint submits a business title change of a worker. The outbound endpoint is incomplete without the data to submit. This data comes from the data entry values on the page widgets. If you declare an `outboundData` element on your page, you have an editable page with input fields for data entry. When you declare those widgets, you also need to declare how the data from the widget binds to your outbound endpoints.

This sample `text` tag in the PMD uses the `valueOutBinding`. Specifying `businessTitleChange.proposedBusinessTitle` sends the text value in the `proposedBusinessTitle` request field for the `businessTitleChange` outbound endpoint.

```
{
  "type": "text",
  "id": "title",
  "label": "Business Title",
  "value": "<% workerData.businessTitle %>",
  "valueOutBinding":"businessTitleChange.proposedBusinessTitle"
},
```

If we add `outboundData` to the sample `workerProfile` PMD, the text widgets automatically become editable. The `valueOutBinding` attribute binds the input data to the `proposedBusinessTitle` field of the `businessTitleChange` outbound endpoint. When the user clicks the <b>Submit</b> button on the page, Presentation Components use the `valueOutBinding` declaration to construct a JSON document and submit it to the outbound endpoints. In this example, the `businessTitleChange` endpoint receives this JSON document as its request HTTP POST request body:

```
{
   "proposedBusinessTitle" : "Vice-President"
}
```

If the other tags use `valueOutBinding` to bind the sample `businessTitleChange` outbound endpoint, Presentation Components include their input data values to their specified path within the same JSON document.

## <a id="section_script"></a>Script

The `script` property enables you to declare custom functions that the PMD tags can call. Use the PMD Scripting syntax and API to code logic with the data and user interactions on the page. The functions you declare in the script block are available to all widgets within the same PMD. For more information, see [Concept: PMD Scripting](/wcp_docs/oli1581402304020.html).

## <a id="section_gsr_yz5_qwb"></a>Security Domains

The `securityDomains` property is a list of security domains that grant or block access to a page. These security domains are model components within the app.

<b>Note:</b> Because Workday doesn't apply contextual security to the pages of an app, we recommend that you use only unconstrained role-based security groups for page security. Constrained security on the pages of an app is derived from the endpoint authentication scheme.

To enable a security domain for page security, open the `.securitydomain` file and set the `enabledForPageSecurity` property to true.

You can specify a maximum of 3 security domains on a page.

Use `securityDomains` on view and edit pages.

For more information, see [securityDomains](/wcp_docs/dvw1628813465101.html).

## <a id="section_1"></a>Comments

To add comments in a PMD, you can add the `_comment` attribute to a PMD tag. To add comments inside a PMD script, you can begin a single line with `//` or enclose multiple lines with `/* */`. Note that because a PMD is a JSON file, you can't use `//` and `/* */` with JSON tags.

This sample endpoint uses the `_comment` attribute.

```
{
  "name": "updatePayInput",
  "baseUrlType": "workday-payroll",
  "url": "<% 'payrollInputs/' + queryParams.donationId %>",
  "httpMethod": "PATCH", 
  "exclude": "<% payInput.fieldEditability != 'endDateOnly' %>",
  "_comment": "If the donation has triggered a deduction, we will update the payInput with a new endDate."
}
```

<b>Note:</b> If you generate a PMD in App Builder, it inserts comments using the `_generationNote`. You can also use this attribute to add comments.

:

```
{
  "name": "createCharityFiles",
  "baseUrlType": "app",
  "url": "charityFilesCollection",
  "authType": "sso",
  "httpMethod": "POST",
  "onMultiPartSend": "<%
    for (var file : self.data.metadata.charityFiles) { //loop through as many files as were uploaded
      /* Put an uploadedBy object with an id field to the JSON part.
         Then put uploadedDate field to the JSON part. */
      file.put('uploadedBy',{'id': worker.id}); //put the new uploadedBy map in the metadata. This captures the WID of the uploader.     
      file.uploadedDate = date:getTodaysDate(date:getDateTimeZone(userTimeZone)); //put the uploadedDate field in the metadata
      file.put('charity',{'id': charity.id}); //link the file with the charity
      console.info('metadata is ' + json:asJSON(self.data)); //log the metadata being passed in for debugging purposes
    }
    self.data;
    %>",
  "exclude": "<% //This exclude statement checks whether a file was uploaded successfully!
        empty attachmentFileUploader.children %>"
}
```

## <a id="section_pgj_kzg_r4b"></a>Sample Apps

For sample PMDs, see the `pmd` files of the sample apps using Presentation Components in the App Catalog. The PMD Widget Dictionary app demonstrates the commonly used PMD tags.

### Related Information

[Concept: Displaying Widgets](/wcp_docs/oqk1573076553441.html)

[Concept: Displaying Data](/wcp_docs/qau1572291138966.html)

[Concept: Submitting Data](/wcp_docs/rmd1572291186381.html)

[Concept: PMD Best Practices](/wcp_docs/asx1597867253394.html)

[Tutorial: Build PMD Page Layouts](https://wd5.myworkday.com/workday/learning/course/86148bed8558101562ab17d35ee10000?type=9882927d138b100019b928e75843018d)

[Reference: Page Metadata](/wcp_docs/opb1667507816853.html)

[Reference: PMD Tags](/wcp_docs/dyg1528862158582.html)

[App Catalog: PMD Widget Dictionary](/app-catalog/pmdWidgetDictionary)

