Write JavaScript
This action executes javascript code on a website.
References to Variables and Tables: Using getRef()
and setRef()
getRef()
and setRef()
Use a reference from a variable or a table:
await getRef({ ref_id: 123, name: 'column or variable name' });
Save a value to a variable or a table:
await setRef({ ref_id: 123, name: 'column or variable name', value: 'something' });
What is ref_id
and where to find it?
ref_id
and where to find it?ref_id
corresponds to the table id or variables id. In ZeroWork, tables and variables are considered data groups. Each data group has its own id (which is ref_id
), so ref_id
corresponds to the whole table id or to all variables. The individual columns and individual variables are uniquely identified by name.
Table ids can be found on the left sidebar:

// example: get value from a table
const profileName = await getRef({ ref_id: 4372, name: 'Profile Name' });
Variables id (ref_id) can be found in the variables dialog:

// example: save value to a variable
// note: all variables (both 'counter' and 'date') will have the same ref_id
const counter = await getRef({ ref_id: 4379, name: 'counter' });
const date = await getRef({ ref_id: 4379, name: 'date' });
Before moving on to examples, beware that getting table content adheres to ZeroWork dynamic loop behavior, as described below: Write JavaScript.
Examples
Using browser in-built functions:
const selector = document.querySelector("div button");
if (selector) selector.click();
Making a fetch request, which returns an array and saving a value from the first item to a variable:
const res = await fetch(
'https://api.github.com/repos/microsoft/vscode-edge-devtools/issues?state=all&per_page=50&page=1'
);
const resData = await response.json();
// save to a variable
await setRef({ ref_id: 4379, name: "value from 1st item", value: resData[0]["title"] });
Dos and Don'ts When Using getRef()
and setRef()
getRef()
and setRef()
Both
getRef()
andsetRef()
are executed asynchronously. Make sure to wait for response, for example, by usingawait
. Otherwise the code will continue executing without waiting for response.
❌ Won't work
const profileName = getRef({ ref_id: 4372, name: 'Profile Name' });
await setRef({ ref_id: 4372, name: 'New Profile Name', value: profileName });
// since await is missing in getRef, saves [object Object], and it's not what we want
✅ Works
const profileName = await getRef({ ref_id: 4372, name: 'Profile Name' });
await setRef({ ref_id: 4372, name: 'copied profile name', value: profileName });
// properly saves profile name (e.g. "Jane Doe")
Variable and column names are case-sensitive. For example, if the column in your table is named "Profile Name" and you reference to it in lower case, you will get an error.
❌ Won't work
const profileName = await getRef({ ref_id: 4372, name: 'profile name' });
// throws error:
// "Cannot access the value of the variable or column.
// This variable or column does not exist on this workflow"
✅ Works
const profileName = await getRef({ ref_id: 4372, name: 'Profile Name' });
Ensure to use correct data types.
ref_id
is expected to be number or string;name
andvalue
are expected to be strings.
❌ Won't work
const profileName = await getRef({ ref_id: 4372, name: address });
// throws error:
// ReferenceError: address is not defined
✅ Works
const profileName = await getRef({ ref_id: 4372, name: 'address' });
✅ Also works
const columnName = 'address';
const profileName = await getRef({ ref_id: 4372, name: columnName });
Saving Non-String Values with setRef()
setRef()
Whenever you use setRef()
, the value is stringified when it's saved. If the value is, for example, array or object and you need to access it later when calling getRef()
, you need to parse it first to json. See example below.
Assume you need to access the first item's object from the array saved to the variable "animals":

❌ Won't work
const animals = await getRef({ ref_id: 4379, name: "animals" });
const firstAnimal = animals[0]["product"]; // resolves to undefined
await setRef({ ref_id: 4379, name: "first animal", value: firstAnimal });
// throws error: Required arguments ref_id, name or value are missing
✅ Works
const animals = JSON.parse( await getRef({ ref_id: 4379, name: "animals" }) );
const firstAnimal = animals[0]["product"]; // resolves to "cat"
await setRef({ ref_id: 4379, name: "first animal", value: firstAnimal });
Saving or Getting Data Within Loops When Using getRef()
and setRef()
getRef()
and setRef()
getRef()
and setRef()
adhere to ZeroWork in-built loop logic. For example, in order to access value from a table, you need to place Start Repeat building block with dynamic loop type before the Write JavaScript building block.
If you want to append data to a table, you need to place Start Repeat building block with standard loop type before the Write JavaScript building block.
Custom Append Loop Logic without Start Repeat
You can append rows within a custom loop in your code block by providing an argument for appendIndex
.
Beware:
appendIndex
refers to the row number that should be appended.appendIndex: 0
means the first row to be appended. If there are already 3 rows in the table, it will be appended as 4th.When using
appendIndex
, avoid placing Write JavaScript building block inside any ZeroWork in-built loop (by this, Start Repeat building block is meant) - whether nested or not! Otherwise the row indices might get mixed up between ZeroWork in-built loop logic and your custom loop logic, and you might end up with mismatched data.
With that in mind, here is an example of how you can make this scenario work:

And here is the end result:

Copy and try yourself:
const valuesToSave = ["a", "b", "c"];
const TABLE_REF_IF = 4382;
let appendIndex = 0;
for (const value of valuesToSave) {
await setRef({ ref_id: TABLE_REF_IF, name: "value", value, appendIndex });
appendIndex++;
}
Custom looping through existing rows of a table within your code block in order to update data (as opposed to append) is currently not supported. However, in most use cases, adding dynamic loop with Start Repeat is enough to enable this use case. Please let us know if you want this feature to be implemented in our Discord server (#ideas-features-suggestions) while providing an example what you would need it for.
Log to TaskBot Logs with log()
log()
You can define your own log messages by using the function log
.
await log({ message: "Logging something custom" });
Will be shown in your logs like so:

You can include status
parameter, which is optional and accepts "success"
or "fail".
The default is "success". Must be either "fail"
or "success"
.
await log({ message: "Logging something that went wrong", status: "fail" });
Will be shown in your logs highlighted in red:

You can include tag
argument, which is optional and makes your log message appear with a labeled tag in your logs. Must be string.
await log({ message: "Logging something custom", tag: "My Custom Tag" });
Will be shown in your logs with a tag on the right:

Error Handling
ZeroWork in-built error handling behavior will not always apply to your custom code. For example, if you use building block Click Web Element and the selector is not found, normally you will get an error that selector could not be found (after the corresponding timeout) in your logs and the TaskBot run will be interrupted. However, because browser console treats not found selectors differently (by simply returning null
), your TaskBot will continue its run despite the error.
❌ Not recommended
document.querySelector("div button").click();
// might throw error: cannot read properties of null (reading 'click')
✅ Better
const selector = document.querySelector("div button");
if (selector) selector.click();
// alternatively, use try-catch logic to throw custom error, see below
Define custom error messages
You can use custom error handling including custom try-catch logic and define custom behavior on error as well as your own custom error messages. Your custom error messages will be reflected in the logs and error reports. Consider the example below:
const selector = document.querySelector("div button");
if (!selector) throw new Error("My custom error message: div button is not found!");
This is how your custom error message in the logs and error reports will appear:

Here is another example with your own custom try-catch logic:
const doSomething = async (timeout) => {
// some code that relies on timeout (e.g. making http request)
};
let timeOut = 10; // corresponds to 10 sec
try {
await doSomething(timeOut);
} catch (e) {
timeOut = timeOut + 10;
if (e.message.includes("timeout" && timeOut < 50) await doSomething(timeOut);
else throw e;
}
// the error message from e.message will be saved to the logs and the error reports
Using delay()
delay()
The custom delay()
method allows you to pause the execution of JavaScript code for a specified duration.
await delay({ min: <number in ms>, max?: <number in ms (optional)> });
How It Works:
min
: The minimum duration for the delay in milliseconds (required). Must be number.max
: The maximum duration for the delay in milliseconds (optional). Must be number. If provided, the actual delay duration will be randomized betweenmin
andmax
.If
max
is not specified, the delay will last exactlymin
milliseconds.If
max
is less thanmin
, the delay will default tomin
milliseconds.
Run Locally in the App (outside browser context)
This option allows the JavaScript code to execute directly in the ZeroWork agent application, bypassing the browser. By running locally, you gain access to additional system features and tools that are not available in the browser environment.
Accessible Libraries
Access to Playwright
pw
: Full access to the Playwright library.
Example:
const browser = await pw.chromium.launch({ channel: "chrome", headless: false });
const context = await browser.newContext();
const page = await context.newPage();
// do something with the new page
await page.goto('https://wikipedia.org');
// end run
await page.close();
await context.close();
await browser.close();
Access to node.js file system
fs
: Node.js file system operations.
Example:
const doesPathExist = fs.existsSync('/some-path');
Access to axios
axios
: HTTP requests using the Axios library.
Example:
const someData = await axios.get('https://api.example.com/data');
Accessible Objects
Access to the active page
activePage
: Access the current active browser page.
This refers to the page your TaskBot is using during its run.
It is designed to combine no-code and code actions. For example, you might initiate a new page with the Open Link building block, perform some actions with some other building blocks, and then use custom Playwright code for advanced actions.
Notes:
The
activePage
is a PlaywrightPage
object. Any methods described in the Playwright Page class documentation are applicable.If no page exists (e.g., because it was not initiated with Open Link or was closed with the Switch or Close Tab building block),
activePage
will benull
.
Examples:
Performing actions not available in ZeroWork:
await activePage.dragAndDrop('#source', '#target');
Adding event listeners:
activePage.on('requestfailed', request => {
await log({
message: request.url() + ' ' + request.failure().errorText,
status: 'fail'
});
});
Access to the active context
taskbotContext
: Access the current active browser context.
This allows integration of code and no-code actions at the context level. A context is one level above a page.
Notes:
The
taskbotContext
is a PlaywrightBrowserContext
object. Any methods described in the Playwright BrowserContext class documentation are applicable.If no browser exists (e.g., because it was not initiated with Open Link or was closed with the Switch or Close Tab building block),
taskbotContext
will benull
.
Examples:
Getting all pages:
const allPages = taskbotContext.pages();
// Do something with the pages
// For example, save all page URLs to a table
let appendIndex = 0;
for (const page of allPages) {
await setRef({ ref_id; 4382, name: "URL", value: page.url(), appendIndex });
appendIndex++;
}
Programmatically adding cookies:
const cookieObject1 = JSON.parse(await getRef({ ref_id: 123, name: "fb_cookies" }));
const cookieObject1 = JSON.parse(await getRef({ ref_id: 123, name: "ig_cookies" }));
await taskbotContext.addCookies([cookieObject1, cookieObject2]);
Additional Notes
Output from
console.log()
will not appear in the browser console since the code runs directly in the ZeroWork application. Tip: Useawait log({ message })
to log messages in the TaskBot Run Reports and running logs.
Using In-Built References Instead of getRef()
getRef()
You might be used to inserting references directly from the dialog options. By this, we are referring to these options:
You can continue using these options. However, there are two caveats:
The values are replaced before the code is executed. If you need dynamic getting and setting behavior within your code, you need to use
getRef()
andsetRef()
.Beware to not change the way references are pasted when using these options - for example, when using these in-built options, the name is not a string. This is intended and not to be confused with the arguments used in
getRef()
.
Last updated
Was this helpful?