Advanced Automation Techniques
Chaining scripts, persistent workflows, debugging strategies, and power-user patterns.
Table of Contents
- Chaining Scripts Together
- Sustainable Growth Cycles
- State Management Across Sessions
- Debugging Techniques
- DOM Discovery & Selector Updates
- Custom Script Patterns
- Performance Optimization
- Account Safety Strategies
Chaining Scripts Together
Scripts coexist in the same browser tab because they all share window.XActions. The order you paste them determines what's available.
Pattern 1: Growth + Protection + Tracking
1. Paste core.js → window.XActions.Core ready
2. Paste sessionLogger.js → Starts logging all actions
3. Paste protectActiveUsers.js → Scans your posts, builds whitelist
4. Paste growthSuite.js → Growth automation runs
What happens: sessionLogger records everything. protectActiveUsers writes to xactions_protected_users. smartUnfollow (inside growthSuite) skips protected users. The session log captures the full audit trail.
Pattern 2: Research → Follow → Engage
1. Paste core.js
2. Paste actions.js → Full XActions.* API
3. Navigate to a viral tweet in your niche
4. Paste followEngagers.js → Follow the likers
5. Paste autoLiker.js → Like related content
What happens: followEngagers builds a list of engaged users. autoLiker independently likes matching content on the page. Both track their actions separately.
Pattern 3: Control Panel + Any Script
1. Paste core.js
2. Paste controlPanel.js → Floating UI appears
3. Select an automation from the dropdown
4. Configure via the panel's inputs
5. Click Start
What happens: The control panel replaces individual script configuration. It provides visual controls for start/pause/resume and real-time progress tracking.
Pattern 4: Actions Library Interactive Use
1. Paste core.js
2. Paste actions.js
3. Run commands interactively:
// Interactive exploration
await XActions.search.advanced({
from: 'elonmusk',
minFaves: 1000,
since: '2025-01-01',
});
// Get results and like them
const tweets = XActions.search.getResults();
for (const tweet of tweets.slice(0, 5)) {
await XActions.engage.like(tweet);
await XActions.Core?.sleep(2000); // Access Core through closure
}
// Export your bookmarks
const bookmarks = await XActions.utils.exportBookmarks(100);
console.table(bookmarks);
Sustainable Growth Cycles
The Weekly Cycle
| Day | Action | Script |
|---|---|---|
| Mon-Fri | Follow 20 targeted users | keywordFollow.js |
| Mon-Fri | Like 30 posts in your niche | autoLiker.js |
| Saturday | Scan posts for engaged users | protectActiveUsers.js |
| Sunday | Unfollow non-followers from 7+ days ago | smartUnfollow.js |
Setting Up the Cycle
Monday-Friday:
// keywordFollow.js config
const OPTIONS = {
KEYWORDS: ['your niche keyword 1', 'your niche keyword 2'],
MAX_FOLLOWS_PER_KEYWORD: 10,
MAX_FOLLOWS_TOTAL: 20,
MIN_FOLLOWERS: 100,
MAX_FOLLOWERS: 50000,
MUST_HAVE_BIO: true,
};
Every follow is recorded with a timestamp in xactions_followed_users.
Saturday:
// protectActiveUsers.js config
const CONFIG = {
POSTS_TO_SCAN: 20, // Check your last 20 posts
};
Builds list of users who engage with your content.
Sunday:
// smartUnfollow.js config
const OPTIONS = {
DAYS_TO_WAIT: 7, // 1 week grace period
MAX_UNFOLLOWS: 50,
DRY_RUN: true, // Run dry first to preview!
ONLY_TRACKED: true, // Only unfollow users we tracked from keywordFollow
WHITELIST: [],
};
Growth Math
If you follow 20 users/day and ~40% follow back:
- Week 1: +100 follows → ~40 new followers
- Week 2: +100 more → ~40 more followers, unfollow ~60 non-followers from Week 1
- Month 1: ~160 new followers, following count stays stable
State Management Across Sessions
How Data Persists
| Storage | Survives Refresh | Survives Tab Close | Used For |
|---|---|---|---|
localStorage (via Core.storage) |
✅ | ✅ | Tracked users, liked tweets, rate limits |
sessionStorage |
✅ | ❌ | Navigation state, processed pages |
| In-memory variables | ❌ | ❌ | Current session counters |
Viewing All Stored Data
// List all XActions keys
window.XActions.Core.storage.list();
// View specific data
window.XActions.Core.storage.get('followed_users');
window.XActions.Core.storage.get('liked_tweets');
window.XActions.Core.storage.get('my_followers');
window.XActions.Core.storage.get('protected_users');
window.XActions.Core.storage.get('session_log');
// View rate limit status
window.XActions.Core.rateLimit.getRemaining('follow', 100, 'day');
window.XActions.Core.rateLimit.getRemaining('like', 200, 'day');
Exporting Data
// Export all XActions data as JSON
const allData = {};
window.XActions.Core.storage.list().forEach(key => {
allData[key] = window.XActions.Core.storage.get(key);
});
console.log(JSON.stringify(allData, null, 2));
// Copy to clipboard
copy(JSON.stringify(allData, null, 2));
Importing Data (Restore from Backup)
const backup = { /* your exported data */ };
Object.entries(backup).forEach(([key, value]) => {
window.XActions.Core.storage.set(key, value);
});
Clearing Data
// Clear specific key
window.XActions.Core.storage.remove('followed_users');
// Clear all XActions data
window.XActions.Core.storage.clear();
// Nuclear option — clear ALL X data from localStorage
XActions.utils.clearXData(); // Requires actions.js loaded
Debugging Techniques
Enable Verbose Logging
window.XActions.Core.CONFIG.DEBUG = true;
Check Extraction Quality
After running any script that extracts user data:
window.XActions.Core.extractionStats.report();
This shows which extraction strategies are working:
📊 Extraction Strategy Report:
bio: 45 extractions
testid: 40 (88.9%) ████████████████
dir-auto: 5 (11.1%) ██
If testid drops below 50%, X has changed their DOM. Check dom-selectors.md for updates.
Visual DOM Inspector
// After loading actions.js:
XActions.utils.devMode();
This outlines every data-testid element in red with tooltip labels. Hover over elements to see their selector names.
Find All Selectors on Current Page
XActions.utils.getAllSelectors();
// Returns sorted array of all data-testid values
Check Rate Limit Status
['follow', 'like', 'unfollow', 'comment'].forEach(action => {
const hourly = window.XActions.Core.rateLimit.getRemaining(action, 50, 'hour');
const daily = window.XActions.Core.rateLimit.getRemaining(action, 200, 'day');
console.log(`${action}: ${hourly} left this hour, ${daily} left today`);
});
Test DOM Selection Without Acting
const { SELECTORS } = window.XActions.Core;
// Count tweets on page
document.querySelectorAll(SELECTORS.tweet).length;
// Check if follow buttons exist
document.querySelectorAll(SELECTORS.followButton).length;
// Test user extraction on first cell
const cell = document.querySelector(SELECTORS.userCell);
if (cell) console.log(window.XActions.Core.extractUserFromCell(cell));
DOM Discovery & Selector Updates
X/Twitter changes their DOM frequently. Here's how to find new selectors:
Method 1: devMode()
XActions.utils.devMode();
// Now hover over elements — each data-testid is shown as a tooltip
Method 2: Element Inspector
- Right-click any element → Inspect
- Look for
data-testidattribute in the element tree - That's your selector:
[data-testid="the-value"]
Method 3: JavaScript Discovery
// Find all data-testid values on the page
const selectors = new Set();
document.querySelectorAll('[data-testid]').forEach(el => {
selectors.add(el.getAttribute('data-testid'));
});
console.log([...selectors].sort());
Method 4: Monitor New Selectors
// Watch for new data-testid elements appearing
const observer = new MutationObserver(mutations => {
for (const mutation of mutations) {
for (const node of mutation.addedNodes) {
if (node.nodeType === 1) {
const testId = node.getAttribute?.('data-testid');
if (testId) console.log('New element:', testId);
node.querySelectorAll?.('[data-testid]').forEach(el => {
console.log('New element:', el.getAttribute('data-testid'));
});
}
}
}
});
observer.observe(document.body, { childList: true, subtree: true });
Custom Script Patterns
Template: Custom Automation Script
(() => {
if (!window.XActions?.Core) {
console.error('❌ Core module not loaded! Paste core.js first.');
return;
}
const { log, sleep, randomDelay, scrollBy, clickElement,
waitForElement, storage, rateLimit, SELECTORS } = window.XActions.Core;
// ============================================
// CONFIGURATION
// ============================================
const OPTIONS = {
MAX_ACTIONS: 10,
MIN_DELAY: 2000,
MAX_DELAY: 5000,
};
// ============================================
// STATE
// ============================================
let actionCount = 0;
let isRunning = true;
const processed = new Set(storage.get('my_script_processed') || []);
// ============================================
// MAIN LOGIC
// ============================================
const processItem = async (element) => {
// Your logic here
actionCount++;
rateLimit.increment('my_action', 'hour');
log(`Action #${actionCount}`, 'success');
};
const run = async () => {
log('🚀 Starting custom automation...', 'info');
while (isRunning && actionCount < OPTIONS.MAX_ACTIONS) {
// Check rate limits
if (!rateLimit.check('my_action', 50, 'hour')) {
log('Rate limit reached', 'warning');
break;
}
// Find elements to process
const elements = document.querySelectorAll(SELECTORS.tweet);
for (const el of elements) {
if (!isRunning || actionCount >= OPTIONS.MAX_ACTIONS) break;
await processItem(el);
await randomDelay(OPTIONS.MIN_DELAY, OPTIONS.MAX_DELAY);
}
// Scroll for more
scrollBy(600);
await sleep(2000);
}
// Save state
storage.set('my_script_processed', Array.from(processed));
log(`✅ Done! ${actionCount} actions performed.`, 'success');
};
// Stop function
window.stopMyScript = () => {
isRunning = false;
log('Stopping...', 'warning');
};
run();
})();
Pattern: Scroll & Collect (No Actions)
const collectData = async () => {
const data = [];
let lastHeight = 0;
while (data.length < 100) {
const items = document.querySelectorAll('[data-testid="tweet"]');
items.forEach(item => {
const link = item.querySelector('a[href*="/status/"]')?.href;
const text = item.querySelector('[data-testid="tweetText"]')?.textContent;
if (link && !data.find(d => d.link === link)) {
data.push({ link, text: text?.substring(0, 100) });
}
});
window.scrollTo({ top: document.body.scrollHeight, behavior: 'smooth' });
await window.XActions.Core.sleep(2000);
if (document.body.scrollHeight === lastHeight) break;
lastHeight = document.body.scrollHeight;
}
return data;
};
const results = await collectData();
console.table(results);
Performance Optimization
Delay Tuning
| Risk Level | Min Delay | Max Delay | Actions/Hour |
|---|---|---|---|
| Conservative | 5000ms | 10000ms | ~25 |
| Moderate | 2000ms | 5000ms | ~50 |
| Aggressive | 1000ms | 2000ms | ~100+ |
Recommendation: Start conservative. Only increase speed after testing for weeks without issues.
Memory Management
Long-running scripts (algorithmTrainer, autoCommenter with monitoring) can accumulate data:
// Check memory of tracked sets
const followed = window.XActions.Core.storage.get('followed_users');
console.log(`Tracking ${Object.keys(followed || {}).length} users`);
// Prune old entries (older than 30 days)
const cutoff = Date.now() - (30 * 24 * 60 * 60 * 1000);
for (const [user, data] of Object.entries(followed)) {
if (data.followedAt < cutoff) delete followed[user];
}
window.XActions.Core.storage.set('followed_users', followed);
Account Safety Strategies
The 80/20 Rule
Keep your automation-to-manual ratio at 80% manual, 20% automated (by volume). Use automation for the tedious parts (finding users, scrolling) and do genuine engagement manually.
Warm-Up Period
New accounts should not run automation immediately. Use the algorithm scripts first:
Week 1-2: algorithmTrainer.js only (browsing, not acting)
Week 3: Add autoLiker.js with very low limits (5-10/day)
Week 4: Add keywordFollow.js with very low limits (5-10/day)
Month 2+: Gradually increase limits
Signs You're Being Rate Limited
- Actions start failing silently
- Follow buttons don't respond
- You see "You are unable to perform this action" messages
- Toast notifications about limits appear
What to do:
- Stop all automation immediately
- Wait at least 1 hour (24 hours if severe)
- Reduce your limits by 50%
- Increase delays between actions
What NOT to Do
- Don't run the same script across multiple browser tabs
- Don't exceed 100 follows/day or 200 likes/day
- Don't comment the same text repeatedly
- Don't automate 24/7 without breaks
- Don't run automation on accounts less than 1 month old