Custom JavaScript gives developers fine-grained control over page manipulation before Changeflow captures content. If you know how to work with the DOM using JavaScript or jQuery, you can write custom scripts that run on the page.

This is an advanced feature for programmers. Most users should use Page Actions instead, which lets you describe interactions in plain English.

When editing a source, you'll find the Custom JavaScript field in the Advanced Settings section:

Advanced Settings section

How It Works

Your JavaScript code runs directly in the page context at a specific point in Changeflow's process:

  1. Page loads fully (Changeflow waits for network activity to settle)
  2. Any natural language Page Actions execute
  3. Your Custom JavaScript runs here
  4. Page is analysed and screenshotted

This timing means the page is fully loaded and interactive when your code runs, but you still have a chance to manipulate the DOM before Changeflow captures and analyses the content.

Writing Custom JavaScript

jQuery is Available

You can use jQuery with the $ selector just like normal:

$('.cookie-banner').hide();
$('.show-more').click();

Behind the scenes, Changeflow namespaces jQuery to avoid conflicts, but you write code using the standard $ syntax.

Sleep Helper

Use await sleep(ms) to pause execution. This is useful for waiting for content to load after triggering an action:

$('.load-more').click();
await sleep(2000);  // Wait 2 seconds for content to load

Automatic Waits Between Commands

Changeflow automatically inserts a 300ms pause between lines of code that end with a semicolon. This prevents race conditions when chaining multiple DOM operations:

// You write:
$('.first-btn').click();
$('.second-btn').click();

// Changeflow executes with automatic waits:
// $('.first-btn').click();
// [300ms pause]
// $('.second-btn').click();

If you need longer pauses, use await sleep() explicitly.

Async/Await Support

Your script is wrapped in an async function, so await works automatically. The browser waits for your script to complete before capturing the page.

$('.expand-all').click();
await sleep(1000);
$('.load-comments').click();
await sleep(2000);

Special CSS Classes

Changeflow uses special CSS classes to control what content is included or excluded from change detection:

Exclude Content

Add changeflow-ignore to elements you want excluded from change detection:

// Exclude sidebar from change detection
$('.sidebar').addClass('changeflow-ignore');

// Exclude ads and promotional content
$('.ads, .promo-banner').addClass('changeflow-ignore');

// Exclude dynamic timestamps that change on every visit
$('.last-updated').addClass('changeflow-ignore');

Include Content

Add changeflow-include to ensure elements are always included in the captured content, even if they would normally be filtered out (empty elements, hidden content, or content outside the monitored section):

// Always include footer info even if outside main section
$('.footer-info').addClass('changeflow-include');

// Preserve metadata that might appear empty
$('.price-data').addClass('changeflow-include');

Complete Example

Here's a real-world example that handles a complex page:

// Dismiss any remaining popups
$('.modal-overlay').hide();
$('.notification-popup').remove();

// Expand collapsed sections
$('.accordion-header.collapsed').click();
await sleep(500);

// Load more content
$('.show-all-results').click();
await sleep(2000);

// Exclude noisy elements from change detection
$('.social-share, .related-articles').addClass('changeflow-ignore');
$('.timestamp, .view-count').addClass('changeflow-ignore');

// Ensure key data is always captured
$('.pricing-table, .availability').addClass('changeflow-include');

Common Use Cases

Hide Dynamic Elements

Exclude elements that change on every page load but aren't meaningful changes:

// Timestamps, counters, session IDs
$('.timestamp').addClass('changeflow-ignore');
$('.visitor-count').addClass('changeflow-ignore');
$('.session-id').addClass('changeflow-ignore');

Expand Hidden Content

Click elements to reveal content that's hidden by default:

// Expand all FAQ answers
$('.faq-question').click();
await sleep(500);

// Open all tabs
$('.tab-header').each(function() {
  $(this).click();
});
await sleep(1000);

Remove Obstructions

Remove elements that obscure content:

// Remove overlay
$('.overlay').remove();

// Hide sticky elements
$('.sticky-header, .sticky-footer').hide();

Wait for AJAX Content

Wait for dynamically loaded content:

// Trigger load and wait
$('.load-more').click();
await sleep(3000);

// Or wait for specific element to appear
let attempts = 0;
while ($('.results-loaded').length === 0 && attempts < 10) {
  await sleep(500);
  attempts++;
}

Tips

Combine with Page Actions

Custom JavaScript runs after natural language Page Actions. Use Page Actions for complex interactions (login, form filling) and Custom JavaScript for fine-tuning:

  • Page Actions: Login with [email protected] password123, click Reports
  • Custom JavaScript: $('.ads').addClass('changeflow-ignore');

Test in Browser DevTools

Test your jQuery selectors in your browser's DevTools console first. If $('.my-selector') works in the console, it will work in Custom JavaScript.

Keep It Simple

Start with minimal code and add complexity only as needed. Simple scripts are easier to debug and maintain.

Handle Missing Elements

Your selectors might not match on every page load. jQuery handles missing elements gracefully (no errors), but be aware that .click() on an empty selection does nothing.

Troubleshooting

Script not running: Make sure your JavaScript syntax is valid. Check for missing semicolons, unmatched brackets, or typos.

Elements not found: Verify your selectors match the actual page structure. The page might load differently in a headless browser than in your desktop browser.

Timing issues: If content isn't loading in time, increase your sleep() durations. Some pages need several seconds for AJAX content.

Changes still detected in excluded areas: Make sure you're adding the class before the page is captured. Place addClass('changeflow-ignore') calls early in your script.

Tag-Level Custom JavaScript

You can configure Custom JavaScript on tags as well as individual sources. This is useful when monitoring many pages from the same website that need the same DOM manipulations.

How It Works

  • Source has no custom JS → Uses tag's custom JS (inheritance)
  • Source has custom JS → Uses source's custom JS (override)

Setting custom JavaScript on a tag means all sources with that tag will run that script automatically, unless a source has its own script defined.

For example, if all pages on a competitor's site have the same noisy elements you want to ignore, add the addClass('changeflow-ignore') calls to the tag once rather than each source.

When to Use Custom JavaScript

Use Custom JavaScript when:

  • You need to exclude specific dynamic elements from change detection
  • You want fine-grained control over which page sections are monitored
  • Page Actions alone aren't achieving what you need
  • You're comfortable writing JavaScript/jQuery code

For most use cases, Page Actions with natural language instructions will be simpler and sufficient.


Your Custom JavaScript code is encrypted in our database for security.