Documentation>Script Performance Optimization
Advanced Level

Script Performance Optimization

Advanced techniques to make your Google Ads scripts run faster, consume fewer resources, and operate within platform limits.

15 minutes
Execution Speed
  • Efficient data filtering
  • Minimize API calls
  • Batch operations
  • Smart caching
Resource Usage
  • Memory management
  • Time limit awareness
  • Operation count limits
  • Error handling
Scalability
  • Large account handling
  • Parallel processing
  • Data pagination
  • Progressive optimization
Platform Limits & Constraints

🚨 Google Ads Scripts Limits

  • Execution time: 30 minutes maximum
  • API operations: 250,000 per run
  • Memory usage: Limited (varies)
  • Concurrent runs: One per script
  • URL fetch: 1,000 calls per run
  • Email sends: 100 per day
  • File size: 100KB script limit
  • Sheets access: Rate limited

💡 Optimization Strategies

  • • Use efficient .withCondition() filters to reduce data set size
  • • Process campaigns/ad groups in batches of 500-1000
  • • Cache frequently accessed data to avoid repeated API calls
  • • Implement checkpoints for long-running processes
  • • Use preview mode to test without consuming operation limits
Efficient Data Filtering

❌ Inefficient Approach

// Bad: Gets ALL campaigns first
const campaigns = AdsApp.campaigns().get();

while (campaigns.hasNext()) {
  const campaign = campaigns.next();
  const stats = campaign.getStatsFor('LAST_7_DAYS');
  
  // Filter AFTER getting data
  if (stats.getCost() > 100 && 
      campaign.isEnabled()) {
    // Process campaign
  }
}

✅ Efficient Approach

// Good: Filter BEFORE getting data
const campaigns = AdsApp.campaigns()
  .withCondition('Status = ENABLED')
  .withCondition('Cost > 100 DURING LAST_7_DAYS')
  .get();

while (campaigns.hasNext()) {
  const campaign = campaigns.next();
  // Only process relevant campaigns
  processCampaign(campaign);
}

🎯 Smart Filtering Tips

  • &• Always filter by status first: 'Status = ENABLED'
  • &• Use performance filters: 'Cost > X DURING LAST_N_DAYS'
  • &• Combine conditions to narrow scope: 'Clicks > 10 AND Conversions > 0'
  • &• Order by most important metric first: .orderBy('Cost DESC')
  • • Limit results when possible: .withLimit(1000)
Batch Processing Techniques
// Efficient batch processing for large accounts
function processCampaignsInBatches() {
  const BATCH_SIZE = 500;
  const MAX_OPERATIONS = 200000; // Stay under 250k limit
  let operationCount = 0;
  
  const campaigns = AdsApp.campaigns()
    .withCondition('Status = ENABLED')
    .orderBy('Cost DESC')
    .get();
  
  const campaignBatch = [];
  
  while (campaigns.hasNext() && operationCount < MAX_OPERATIONS) {
    campaignBatch.push(campaigns.next());
    
    // Process batch when full or at end
    if (campaignBatch.length >= BATCH_SIZE || !campaigns.hasNext()) {
      operationCount += processBatch(campaignBatch);
      campaignBatch.length = 0; // Clear batch
      
      // Log progress
      Logger.log(`Processed batch. Operations used: ${operationCount}`);
    }
  }
  
  Logger.log(`Total operations: ${operationCount}`);
}

function processBatch(campaigns) {
  let operations = 0;
  
  campaigns.forEach(campaign => {
    const stats = campaign.getStatsFor('LAST_7_DAYS');
    operations += 2; // One for campaign, one for stats
    
    // Your optimization logic here
    if (stats.getCost() > 0) {
      // Process campaign
      operations += 1; // Additional operation for changes
    }
  });
  
  return operations;
}

✅ Batch Benefits

  • • Reduces memory usage
  • • Enables progress tracking
  • • Allows early termination
  • • Better error recovery

🔧 Implementation Tips

  • • Use arrays to collect batch items
  • • Clear arrays after processing
  • • Track operation counts
  • • Log batch completion
Performance Monitoring
// Performance monitoring and limits checking
function main() {
  const startTime = new Date();
  const MAX_RUNTIME_MINUTES = 25; // Stay under 30min limit
  let operationCount = 0;
  
  Logger.log('Script started at: ' + startTime.toLocaleString());
  
  // Your main script logic here
  const campaigns = AdsApp.campaigns()
    .withCondition('Status = ENABLED')
    .get();
  
  while (campaigns.hasNext()) {
    // Check time limit
    const elapsed = (new Date() - startTime) / (1000 * 60);
    if (elapsed > MAX_RUNTIME_MINUTES) {
      Logger.log(`Time limit reached: ${elapsed.toFixed(1)} minutes`);
      break;
    }
    
    // Check operation limit
    if (operationCount > 200000) {
      Logger.log(`Operation limit reached: ${operationCount}`);
      break;
    }
    
    const campaign = campaigns.next();
    operationCount += processCampaign(campaign);
    
    // Log progress every 100 campaigns
    if (operationCount % 100 === 0) {
      Logger.log(`Progress: ${operationCount} operations, ${elapsed.toFixed(1)}min elapsed`);
    }
  }
  
  const totalTime = (new Date() - startTime) / 1000;
  Logger.log(`Script completed in ${totalTime.toFixed(1)} seconds using ${operationCount} operations`);
}

function processCampaign(campaign) {
  // Return the number of operations used
  return 2; // Example: getting campaign + stats
}

Always monitor execution time and operation count to prevent script timeouts and ensure reliable performance.