Multi-line JavaScript Evaluation
The evaluate
mutation allows you to execute JavaScript in the browser's page environment. For multi-line scripts, you must wrap your code in an IIFE (Immediately Invoked Function Expression) using triple quotes:
mutation MultiLineEvaluate {
goto(url: "https://example.com") {
status
}
evaluate(content: """
(() => {
try {
const title = document.title;
const url = window.location.href;
return JSON.stringify({ title, url, error: null });
} catch (e) {
return JSON.stringify({ title: null, url: null, error: (e?.message ?? String(e)) });
}
})()
""") {
value
}
}
Key requirements:
- Use triple quotes (
"""
) for multi-line code - Wrap your code in an IIFE:
(()=>{ ... })()
- Return values from your code execution
Example use cases:
- Extract complex data from the DOM
- Manipulate page elements dynamically, such as deleting or adding elements to the HTML
- Perform calculations or transformations
Advanced Examples
Extracting Complex Data
mutation ExtractComplexData {
goto(url: "https://example.com") {
status
}
evaluate(content: """
(() => {
try {
// Extract all links with their text and href
const links = Array.from(document.querySelectorAll('a')).map(link => ({
text: link.textContent.trim(),
href: link.href,
isExternal: !link.href.includes(window.location.hostname)
}));
// Get page metadata
const meta = {
title: document.title,
description: document.querySelector('meta[name="description"]')?.content || '',
keywords: document.querySelector('meta[name="keywords"]')?.content || '',
viewport: document.querySelector('meta[name="viewport"]')?.content || ''
};
return JSON.stringify({ links, meta, error: null });
} catch (e) {
return JSON.stringify({ links: null, meta: null, error: (e?.message ?? String(e)) });
}
})()
""") {
value
}
}
Dynamic Element Manipulation
mutation ManipulateElements {
goto(url: "https://example.com") {
status
}
evaluate(content: """
(() => {
try {
// Remove all ads
const ads = document.querySelectorAll('[class*="ad"], [id*="ad"], [class*="banner"]');
ads.forEach(ad => ad.remove());
// Add a custom element
const customDiv = document.createElement('div');
customDiv.innerHTML = '<h2>Custom Content Added by BrowserQL</h2>';
customDiv.style.cssText = 'background: #f0f0f0; padding: 20px; margin: 20px 0; border-radius: 5px;';
document.body.insertBefore(customDiv, document.body.firstChild);
return JSON.stringify({
removedAds: ads.length,
addedElement: 'Custom div added to page',
error: null
});
} catch (e) {
return JSON.stringify({ removedAds: null, addedElement: null, error: (e?.message ?? String(e)) });
}
})()
""") {
value
}
}
Data Transformation and Calculations
mutation DataTransformation {
goto(url: "https://example.com") {
status
}
evaluate(content: """
(() => {
try {
// Extract and transform price data
const priceElements = document.querySelectorAll('[class*="price"], [class*="cost"]');
const prices = Array.from(priceElements).map(el => {
const text = el.textContent;
const price = parseFloat(text.replace(/[^0-9.]/g, ''));
return {
originalText: text,
numericValue: price,
currency: text.match(/[$€£¥]/)?.[0] || 'unknown'
};
}).filter(p => !isNaN(p.numericValue));
// Calculate statistics
const total = prices.reduce((sum, p) => sum + p.numericValue, 0);
const average = prices.length > 0 ? total / prices.length : 0;
const min = Math.min(...prices.map(p => p.numericValue));
const max = Math.max(...prices.map(p => p.numericValue));
return JSON.stringify({
prices,
statistics: { total, average, min, max, count: prices.length },
error: null
});
} catch (e) {
return JSON.stringify({ prices: null, statistics: null, error: (e?.message ?? String(e)) });
}
})()
""") {
value
}
}
Best Practices
- Always use IIFE: Wrap your code in
(()=>{ ... })()
to avoid variable conflicts - Return meaningful data: Make sure your function returns the data you need
- Handle errors gracefully: Use try-catch blocks for robust error handling
- Keep it focused: Write focused, single-purpose scripts for better maintainability
Next Steps
Ready to explore more advanced BrowserQL features? Check out these related topics: