> For the complete documentation index, see [llms.txt](https://cortex-docs.paloaltonetworks.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://cortex-docs.paloaltonetworks.com/cortex-xsoar-8-on-prem/8.7/configure-cortex-xsoar/dashboards-and-reports/widgets/create-a-custom-widget-using-a-script.md).

# Create a custom widget using a script

You can use scripts in custom widgets to create dynamic widgets for more complex calculations. For examples of creating widgets using scripts, see [Script-based widget examples](#script-based-widget-examples).

{% hint style="info" %}

### Note

Cortex XSOAR supports JavaScript, Python and PowerShell.
{% endhint %}

Before creating a script-based widget in the **Widgets Library**, you need to create or upload the script to the **Scripts** page. In the **Widgets Library**, you can define the script arguments and change the visuals.

{% hint style="info" %}

### Note

If you upload a script to the **Scripts** page, the **Arguments** field is automatically updated. You can then define the arguments in the widget builder. If you create a new script (without uploading) in the **Scripts** page, you need to add the arguments manually for them to appear in the **Widgets Library** when creating or editing a widget.
{% endhint %}

### Create a script-based widget

1. In the **Scripts** page, upload or create a new script for one of the following widget types:
   * Text
   * Number
   * Duration
   * Trend
   * Chart
   * Table or list
   * Filter Data for all Widgets (Pivoting)
2. In the **Widgets Library**, create a widget. For more information about creating a widget, see [Create a widget using the widget builder](/cortex-xsoar-8-on-prem/8.7/configure-cortex-xsoar/dashboards-and-reports/widgets/create-a-widget-using-the-widget-builder.md).
3. Select the **Scripts** data type and then add the script to the widget.

   (Upload script only) If you have added arguments, these appear when creating a widget. If you have not uploaded the script, you need to add the arguments manually in the **Scripts** page.
4. Add the script-based widget where relevant, for example to a report, a dashboard, or an incident.

### Script-based widget examples

The following are sample arguments/scripts to create a widget. After creating the widget from a script, add the widget to a dashboard or report. For more details, see [Create a widget using the widget builder](/cortex-xsoar-8-on-prem/8.7/configure-cortex-xsoar/dashboards-and-reports/widgets/create-a-widget-using-the-widget-builder.md).

{% hint style="info" %}

### Note

Add the **widget** tag in the script settings to make the script available for use in script-based widgets. For more information, see [Create a script](/cortex-xsoar-8-on-prem/8.8/configure-cortex-xsoar/playbooks/scripts/create-a-script.md).
{% endhint %}

<details>

<summary>Script argument examples</summary>

To add a time stamp or a use a search query, add the following arguments to a script.

| Argument                            | Description                                                               |
| ----------------------------------- | ------------------------------------------------------------------------- |
| **`demisto.args()[‘from’]`**        | The start date of the time-stamp date range of the widget.                |
| **`demisto.args()[‘to’]`**          | The end date of the time-stamp date range of the widget.                  |
| **`demisto.args()['searchQuery']`** | The search query entered into the search bar at the top of the dashboard. |

</details>

<details>

<summary>Text</summary>

In this example, create a script that queries and returns current on-line users, and displays the data in a markdown table.

In the script, type one of the following return values:

**JavaScript**

**`return executeCommand("getUsers", {online: true})[0].HumanReadable;`**

**Python**

**`demisto.results(demisto.executeCommand("getUsers", { "online": True })[0]["HumanReadable"])`**

When creating or editing the widget in Cortex XSOAR, to add a page break, type **`/pagebreak`** in the text box. When you generate a report, the widgets that follow the page break are on a separate page.

![quick-definitions-pagebreak-2.png](/files/oqX3ZJv0nvvGqyyjqTsT)

In the dashboard, the following widget displays the on-line users:

![onelineusers\_widget.png](/files/z36CM1vb014wJg0GkQA9)

{% hint style="info" %}

### Note

(*Multi-tenant*) Script-based text widgets are not supported in the Main Account.
{% endhint %}

</details>

<details>

<summary>Number</summary>

This example shows how to create a single item widget with the percentage of incidents that DBot closed.

In the script, type one of the following:

**JavaScript**

```programlisting
   var res = executeCommand("getIncidents", {
'query': 'status:closed and investigation.users:""', 
'fromdate': args.from, 
'todate': args.to,
'size': 0 
});
var closedByDbot = res[0].Contents.total;

res = executeCommand("getIncidents", {
  'status': 'closed',
  'fromdate': args.from, 
  'todate': args.to, 
  'size': 0 });
var overallClosed = res[0].Contents.total;

var result = Math.round(closedByDbot * 100 / overallClosed);
return isNaN(result) ? 0 : result;
```

**Python**

```programlisting
res = demisto.executeCommand("getIncidents", {
    "query": "status:closed and investigation.users:\"\"",
    "fromdate": demisto.args()["from"],
    "todate": demisto.args()["to"],
    "size": 0
})
closedByDbot = res[0]["Contents"]["total"]

res = demisto.executeCommand("getIncidents", {
    "status": "closed",
    "fromdate": demisto.args()["from"],
    "todate": demisto.args()["to"],
    "size": 0
})
overallClosed = res[0]["Contents"]["total"]
if overallClosed == 0:
    demisto.results(0)
else:
    result = round(closedByDbot * 100 / overallClosed)
    demisto.results(result)
```

</details>

<details>

<summary>Duration</summary>

In this example, create a script that queries and returns a time duration (specified in seconds), and displays the data as a countdown clock. If using a JSON file, you must set **`widgetType`** to duration.

In the script, type one of the following return values:

**JavaScript**

**`return JSON.stringify([{ name: "", data: [120] }]);`**

**Python**

**`demisto.results('[{"name": "", "data": [120]}]')`**

The return type should be a string (any name) and an integer. The time is displayed in seconds.

After you have uploaded the script and created the widget, you can add the widget to the dashboard or report. The ![duration-2.jpg](/files/7DmuuWDJEBiMEmN68i7k) widget displays the time duration:

![widget-time-example.jpg](/files/cFM2Syx25Qe5hyyCAMdO)

</details>

<details>

<summary>Chart</summary>

A valid result for a chart widget is a list of groups. Each group points to a single entity, for example, in bar charts each group is a bar. A group consists of the following:

* **Name** - A string.
* **Data** - An array of integers.
* **Color** - A string representing a color that will be used as a default color for that group. It can be the name of the color, a hexadecimal representation of the color, or an rgb color value (optional).

  <div data-gb-custom-block data-tag="hint" data-style="info" class="hint hint-info"><h3>Note</h3><p>A widget legend color will override a group color if it exists.</p></div>
* **Groups** - A nested list of groups (optional).

In this example, we show how to create a script that will query and return the trend between two sums in a pie chart.

* Pie
* Line
* Bar
* Column

**Simple pie/chart**

In the script, type the following return value:

**JavaScript**

```programlisting
                                    var data = [
    {name: "2018-04-12", data: [10], color: "blue"},
    {name: "2018-04-10", data: [3], color: "#029be5"},
    {name: "2018-04-17", data: [1], color: "rgb(174, 20, 87)"},
    {name: "2018-04-16", data: [34], color: "grey"},
    {name: "2018-04-15", data: [17], color: "purple"}
];
return JSON.stringify(data);            
```

**Python**

```programlisting
data = [
    {"name": "2018-04-12", "data": [10], "color": "blue"},
    {"name": "2018-04-10", "data": [3], "color": "#029be5"},
    {"name": "2018-04-17", "data": [1], "color": "rgb(174, 20, 87)"},
    {"name": "2018-04-16", "data": [34], "color": "grey"},
    {"name": "2018-04-15", "data": [17], "color": "purple"}
]
demisto.results(json.dumps(data))
```

After you have uploaded the script and created the widget you can add the widget to a dashboard or report.

**Two group chart**

**JavaScript**

```programlisting
var data = [
    {name: "2018-04-12", data: [10], groups: [{name: "Unclassified", data: [10] }]},
    {name: "2018-04-10", data: [3], groups: [{name: "Unclassified", data: [2] }, {name: "Access", data: [1] }]},
    {name: "2018-04-17", data: [1], groups: [{name: "Unclassified", data: [1] }]},
    {name: "2018-04-16", data: [34], groups: [{name: "Unclassified", data: [18] }, {name: "Phishing", data: [14] }]},
    {name: "2018-04-15", data: [17], groups: [{name: "Access", data: [17] }]}
];
return JSON.stringify(data);
```

**Python**

```programlisting
data = [
    {"name": "2018-04-12", "data": [10], "groups": [{"name": "Unclassified", "data": [10] }]},
    {"name": "2018-04-10", "data": [3], "groups": [{"name": "Unclassified", "data": [2] }, {"name": "Access", "data": [1] }]},
    {"name": "2018-04-17", "data": [1], "groups": [{"name": "Unclassified", "data": [1] }]},
    {"name": "2018-04-16", "data": [34], "groups": [{"name": "Unclassified", "data": [18] }, {"name": "Phishing", "data": [14] }]},
    {"name": "2018-04-15", "data": [17], "groups": [{"name": "Access", "data": [17] }]}
]
demisto.results(json.dumps(data))
```

</details>

<details>

<summary>Trend</summary>

In this example, create a script that queries and returns the trend between two sums.

In the script, type one of the following return values:

**JavaScript**

**`return JSON.stringify({currSum: 48, prevSum: 32});`**

**Python**

**`demisto.results({ "currSum": 48, "prevSum": 32 })`**

The return displays an object which compares the current sum with the previous sum.

</details>

<details>

<summary>Table or list</summary>

In this example, you need to create a script that queries and returns employee information in a table. For Table or List, if creating a JSON file, set the widgetType to table or list. When using lists, a maximum of two columns displays, the rest are ignored (do not display).

In the script, type one of the following return values:

**JavaScript**

```programlisting
return JSON.stringify({total: 3, data:[
  {Employee: 'David D', Phone: '+14081234567', Email:
  'David@org.com'},
  {Employee: 'James J', Phone: '+14087654321', Email:
  'James@org.com'}, 
  {Employee: 'Alex A', Phone: '+14087777777', Email:
  'Alex@org.com'}
  ]});
```

**Python**

```programlisting
demisto.results({ "total": 3, "data": [{"Employee": "David D",
 "Phone": "+14081234567", "Email": "David@org.com"}, {"Employee":
 "James J", "Phone": "+14087654321", "Email": "James@org.com"}, 
{"Employee": "Alex A", "Phone": "+14087777777", "Email":
 "Alex@org.com"}]})
```

After you have uploaded the script and created a widget you can add the widget to a dashboard or report. The following widget displays the employee information:

![widget\_example\_employee.png](/files/Ko8KkVrXlU0Ko1vxQ7C0)

</details>

<details>

<summary>Filter data for all widgets (pivoting)</summary>

Example 24. Display filtered incident and indicator data in a widget with a bar graph

In this example, you create a filter according to type (phishing, access and IP) and then pivot to the relevant incident/indicators page. You need to add the following to the JSON or python script.

* **`dataType`**: Pivots to the relevant page, such as Incidents page.
* **`query`**: Filters according to the value in the relevant page. For example, for phishing, if you define **`‘type:Phishing’`** and the **`dataType:incidents`**, you are taken to the Incident page with the **`‘type:Phishing’`** filter.
* **`pivot`**: Filters the dashboard according to data set. For example, **`pivot: “type:Phishing”`** enables you to filter data that relates to phishing in the dashboard.

In the script, type one of the following return values:

**JavaScript**

```programlisting
return JSON.stringify([{name: "Phishing", dataType:"incidents", query:"type:Phishing", data: [50],  pivot: "type:Phishing"},
{name: "Access", dataType:"incidents", query:"type:Access", data: [50], pivot: "type:Access"},
{name: "IP", data: [50], dataType: "indicators", query:"type:IP", pivot:"type:IP"}]);
```

**Python**

```programlisting
data = [
    {"name": "Phishing", "data": [50], "dataType": "incidents", "Query": "type:Phishing",  "pivot": "type:Phishing"},
    {"name": "Access", "data": [50], "dataType": "incidents", "query": "type:Access",  "pivot": "type:"Access"},
    {"name": "IP", "data": [50], "dataType": "indicators", "query": "type:"IP", "pivot": "type:IP"}
]
demisto.results(json.dumps(data))
```

After you upload the script and created a widget, add the widget to a dashboard or report page.

![widget-customfilter-2.png](/files/g2C3lEPJPZROYXWayTgp)

Example 25. Display filtered incident and indicator data in a widget with a line graph

In this example, you create a filter according to type (phishing, access and IP) and then pivot to the relevant incident/indicators page. You need to add the following to the JSON or python automation script.

**JavaScript**

```programlisting
return JSON.stringify([
    {
    "name": "Jan 1, 2024",
    "data": [6],
    "groups": [
      { "name": "Phishing", "data": [1], "pivot": "type:Phishing", "query": "type:Phishing" },
      { "name": "Access", "data": [2], "pivot": "type:Acce", "query": "type:Access" },
      { "name": "IP", "data": [3], "pivot": "type:IP", "query": "type:IP" }
    ]
  },
  {
    "name": "Jan 2, 2024",
    "data": [7],
    "groups": [
      { "name": "Phishing", "data": [2], "pivot": "type:Phishing", "query": "type:Phishing" },
      { "name": "Access", "data": [1], "pivot": "type:Access", "query": "type:Access" },
      { "name": "IP", "data": [4], "pivot": "type:IP", "query": "type:IP" }
    ]
  },
  {
    "name": "Jan 3, 2024",
    "data": [8],
    "groups": [
      { "name": "Phishing", "data": [3], "pivot": "type:Phishing", "query": "type:Phishing" },
      { "name": "Access", "data": [4], "pivot": "type:Access", "query": "type:Access" },
      { "name": "IP", "data": [1], "pivot": "type:IP", "query": "type:IP" }
    ]
  }
]);
```

**Python**

```programlisting
data = [
  {
    "name": "Jan 1, 2024",
    "data": [6],
    "groups": [
      { "name": "Phishing", "data": [1], "pivot": "type:Phishing", "query": "type:Phishing" },
      { "name": "Access", "data": [2], "pivot": "type:Acce", "query": "type:Access" },
      { "name": "IP", "data": [3], "pivot": "type:IP", "query": "type:IP" }
    ]
  },
  {
    "name": "Jan 2, 2024",
    "data": [7],
    "groups": [
      { "name": "Phishing", "data": [2], "pivot": "type:Phishing", "query": "type:Phishing" },
      { "name": "Access", "data": [1], "pivot": "type:Access", "query": "type:Access" },
      { "name": "IP", "data": [4], "pivot": "type:IP", "query": "type:IP" }
    ]
  },
  {
    "name": "Jan 3, 2024",
    "data": [8],
    "groups": [
      { "name": "Phishing", "data": [3], "pivot": "type:Phishing", "query": "type:Phishing" },
      { "name": "Access", "data": [4], "pivot": "type:Access", "query": "type:Access" },
      { "name": "IP", "data": [1], "pivot": "type:IP", "query": "type:IP" }
    ]
  }
]

demisto.results(json.dumps(data));
```

After you upload the script and create a widget, add the widget to a dashboard or report page.

![widget-pivot-line-graph.png](/files/vuwP528YtdZIuamD7ceu)

</details>


---

# 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://cortex-docs.paloaltonetworks.com/cortex-xsoar-8-on-prem/8.7/configure-cortex-xsoar/dashboards-and-reports/widgets/create-a-custom-widget-using-a-script.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.
