ZeroWork
  • 👋Home and Welcome
  • 🚀Getting Started
  • ⬇️Install the Agent
  • 🧑‍💻Crash Course
  • Using ZeroWork
    • 🖥️General: Run, Schedule, Share, Webhooks
      • Run
      • Stop
      • Log in to the Agent
      • Run Modes
        • Run Incognito
        • Run Non-Incognito
        • Run in My Regular Browser
      • Run Settings
        • Run in Background
        • Stay on Page after Run
        • Bring Pages to Front
      • TaskBot Sharing Options
      • Cookies
      • Scheduler
      • Trigger Run via Webhook
      • Proxies
      • Remote (Cloud) Execution
      • How to Check and Update Your Agent
      • Install ZeroWork Agent on VPS
    • 📔Using Selectors
      • What Are Selectors
      • Use Element's Text
      • Copy Selectors
      • How to Build Custom Selectors
        • Basic Concepts of Selectors
        • One Element Can Have Many Selector Expressions
        • Check if Selector Is Correct and Unique
        • Exact or Loose Match
        • Hierarchy
        • Combine Filters with Standard CSS Logic
        • Lists: Incremental CSS Selectors
        • Addressing Siblings
      • How to Use XPath in ZeroWork (advanced)
    • 🏗️Using Building Blocks
      • Open Link
      • Save Page Url
      • Switch or Close Tab
      • Go Back or Forward
      • Switch Frame
      • Browser Alert
      • Click Web Element
      • Check Web Element
      • Save Web Element
        • Save Lists
        • Enrich Existing Data
        • Stop Run If Selector Is Not Found Option
      • Insert Text or Data
      • Hover Web Element
      • Select Web Dropdown
      • Keyboard Action
      • Start Condition and Set Condition
        • Actions = & ≠
        • Actions <, ≤, >, ≥
        • Data Found & Data not Found
        • Contains & Does Not Contain
        • Before (Date) & After (Date)
      • Start Repeat
        • Standard Loop
        • Dynamic Loop
        • Continue until No Element Is Found
        • Auto-Scroll
        • Auto-Continue from Last Row or Element
        • Nested Loops - Handle Pagination
      • After Repeat
      • Break Repeat
      • Try-Catch
      • Raise Error
      • Abort Run
      • Update Data
      • Number Operations
        • Example: Standardize different formats
      • Format Data
        • Remove Words
        • Shorten Content Length
      • Split Data
      • Apply Regex
      • Remove Duplicates
      • Delete Data
      • Ask ChatGPT
      • Send Notification
      • APIs: Send HTTP Request
      • Write JavaScript
      • Save File
      • Upload File
      • Delay
      • Record Date
      • Take Screenshot
      • Save from Clipboard
      • Log
      • Building Block Options
        • Delay Times between the Building Blocks
        • Randomize Delay Time
        • Deactivate Building Blocks
        • Shortcuts
        • Spintax
        • Auto-Align
        • Sticky Notes
    • 🔀Using Variables
    • 💿Using Tables
      • How to Add Tables
      • Native Tables
      • Google Sheets
      • Import Data from CSV
      • Using Google Sheet vs. Native Tables
      • Create Columns
      • Export Data as CSV
      • Convert Native Table to a Google Sheet
    • 📄Using Run Reports
    • 😑Common Problems
      • My TaskBot Does Not Start Run
      • When I Use Data from Table, No Data is Being Pulled
      • Website is Glitching and Flashing
      • No Selector is Found
      • My TaskBot Saves Some Data but Not All
      • Data Is Saved in Wrong Format
      • Website Requires SMS or Email Verification
      • Keyboard Action Is Not Working As Expected
      • Check Web Element Identifies Selector as Found but Next Action Does Not
      • When Using Insert Data Block, First Letters Are Cut Off
      • Workflow Has More than One Starting Building Block
      • TaskBot Does Not Automatically Scroll
  • Support
    • 🆘Getting Support
  • 🆕Release Notes
    • Version 1.1.61
    • Version 1.1.62
    • Version 1.1.63
    • Version 1.1.64
    • Version 1.1.65
    • Version 1.1.66
    • Version 1.1.67
    • Version 1.1.68
Powered by GitBook
On this page
  • References to Variables and Tables: Using getRef() and setRef()
  • Examples
  • Dos and Don'ts When Using getRef() and setRef()
  • Saving Non-String Values with setRef()
  • Saving or Getting Data Within Loops When Using getRef() and setRef()
  • Log to TaskBot Logs with log()
  • Error Handling
  • Using delay()
  • Run Locally in the App (outside browser context)
  • Using In-Built References Instead of getRef()

Was this helpful?

  1. Using ZeroWork
  2. Using Building Blocks

Write JavaScript

PreviousAPIs: Send HTTP RequestNextSave File

Last updated 4 months ago

Was this helpful?

This action executes javascript code on a website.

References to Variables and Tables: Using 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 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: #saving-or-getting-data-within-loops.


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()

  1. Both getRef() and setRef() are executed asynchronously. Make sure to wait for response, for example, by using await. 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")
  1. 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' });
  1. Ensure to use correct data types. ref_id is expected to be number or string; name and value 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()

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() 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++;
}

Log to TaskBot Logs with 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()

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 between min and max.

    • If max is not specified, the delay will last exactly min milliseconds.

    • If max is less than min, the delay will default to min 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

  1. 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();
  1. Access to node.js file system

fs: Node.js file system operations.

Example:

const doesPathExist = fs.existsSync('/some-path');
  1. Access to axios

axios: HTTP requests using the Axios library.

Example:

const someData = await axios.get('https://api.example.com/data');

Accessible Objects

  1. 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:

  • 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 be null.

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'
  });
});
  1. 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:

  • 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 be null.

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: Use await log({ message }) to log messages in the TaskBot Run Reports and running logs.


Using In-Built References Instead of 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:

  1. 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() and setRef().

  2. 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().

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 server (#ideas-features-suggestions) while providing an example what you would need it for.

The activePage is a Playwright Page object. Any methods described in the are applicable.

The taskbotContext is a Playwright BrowserContext object. Any methods described in the are applicable.

🏗️
Discord
Playwright Page class documentation
Playwright BrowserContext class documentation