Tools: WordPress Page Builder Automation: Generate Layouts via Scripts

Tools: WordPress Page Builder Automation: Generate Layouts via Scripts

Why Automate Page Builder Layouts? ## Architecture: JSON Config → Script → Page Builder ## Supported Page Builders ## Example 1: Elementor Automation ## Step 1: Export Template as JSON ## Step 2: Create City Data JSON ## Step 3: PHP Automation Script ## Step 4: Run Script ## Example 2: Divi Layout Automation ## Divi Storage Format ## Divi Automation Script ## Example 3: WP-CLI Integration ## Create WP-CLI Command ## Advanced: REST API Integration ## Create REST Endpoint ## Call API from External Script ## Real-World Use Case: Agency Workflow ## Client: National HVAC Company ## Implementation ## Handling Dynamic Content ## ACF Integration ## Dynamic Elementor Widgets ## Error Handling & Logging ## Bottom Line Client wants: 50 landing pages with same layout, different cities Manual method: 50 Ɨ 15 minutes = 12.5 hours clicking in Elementor!! My response: "Give me 45 minutes to write a script" Here's how to automate page builder layout generation programmatically: Manual page building SUCKS when: Automation = sanity!! This technique works with: Key insight: All page builders store layouts as JSON or shortcodes in database!! Create one perfect page manually in Elementor Saved as: template.json File: generate-elementor-pages.php 3 pages created in seconds!! Divi stores layouts as JSON in _et_pb_page_layout postmeta File: wp-content/mu-plugins/page-generator.php Need: Landing page for every city (300+ locations) Manual time: 300 Ɨ 20 minutes = 100 hours!! Data file: hvac-locations.csv Result: 300 pages generated in 5 minutes!! Elementor renders ACF shortcode dynamically!! Stop clicking page builders for repetitive layouts!! ROI: Pays for itself after 10 pages!! For 50+ pages: Automation is NON-NEGOTIABLE!! Page builder automation = agency superpower!! šŸš€ This article contains affiliate links! Templates let you quickly answer FAQs or store snippets for re-use. Used this exact workflow last month for client with 85 location pages... saved me like 3 DAYS of clicking around in Divi!! Template took 90 min to perfect, wrote the PHP script in 2 hours, then just ran it and boom - 85 pages with unique city content, phone numbers, map embeds, everything. Client was like "how did you do this so fast" lol... JSON config is KEY - once you nail the placeholder system you can pump out pages for ANY repetitive layout. Game changer for agency work honestly... Are you sure you want to ? It will become hidden in your post, but will still be visible via the comment's permalink. as well , this person and/or CODE_BLOCK: cities.json → automation-script.php → wp-cli → 50 pages created CODE_BLOCK: cities.json → automation-script.php → wp-cli → 50 pages created CODE_BLOCK: cities.json → automation-script.php → wp-cli → 50 pages created CODE_BLOCK: Elementor → Tools → Export Template CODE_BLOCK: Elementor → Tools → Export Template CODE_BLOCK: Elementor → Tools → Export Template CODE_BLOCK: { "content": [ { "id": "abc123", "elType": "section", "elements": [ { "elType": "column", "elements": [ { "elType": "widget", "widgetType": "heading", "settings": { "title": "{{CITY_NAME}} Services" } } ] } ] } ] } CODE_BLOCK: { "content": [ { "id": "abc123", "elType": "section", "elements": [ { "elType": "column", "elements": [ { "elType": "widget", "widgetType": "heading", "settings": { "title": "{{CITY_NAME}} Services" } } ] } ] } ] } CODE_BLOCK: { "content": [ { "id": "abc123", "elType": "section", "elements": [ { "elType": "column", "elements": [ { "elType": "widget", "widgetType": "heading", "settings": { "title": "{{CITY_NAME}} Services" } } ] } ] } ] } CODE_BLOCK: [ { "city": "Chicago", "state": "IL", "zip": "60601", "phone": "(312) 555-0100" }, { "city": "Boston", "state": "MA", "zip": "02108", "phone": "(617) 555-0200" }, { "city": "Seattle", "state": "WA", "zip": "98101", "phone": "(206) 555-0300" } ] CODE_BLOCK: [ { "city": "Chicago", "state": "IL", "zip": "60601", "phone": "(312) 555-0100" }, { "city": "Boston", "state": "MA", "zip": "02108", "phone": "(617) 555-0200" }, { "city": "Seattle", "state": "WA", "zip": "98101", "phone": "(206) 555-0300" } ] CODE_BLOCK: [ { "city": "Chicago", "state": "IL", "zip": "60601", "phone": "(312) 555-0100" }, { "city": "Boston", "state": "MA", "zip": "02108", "phone": "(617) 555-0200" }, { "city": "Seattle", "state": "WA", "zip": "98101", "phone": "(206) 555-0300" } ] COMMAND_BLOCK: <?php /** * Elementor Page Generator * Usage: php generate-elementor-pages.php */ // Load WordPress require_once('/path/to/wp-load.php'); // Load data $template = json_decode(file_get_contents('template.json'), true); $cities = json_decode(file_get_contents('cities.json'), true); foreach ($cities as $city) { // Replace placeholders in template $layout = replace_placeholders($template, [ '{{CITY_NAME}}' => $city['city'], '{{STATE}}' => $city['state'], '{{ZIP}}' => $city['zip'], '{{PHONE}}' => $city['phone'] ]); // Create page $page_id = wp_insert_post([ 'post_title' => $city['city'] . ' Services', 'post_status' => 'publish', 'post_type' => 'page', 'post_content' => '' // Elementor uses meta, not content ]); if (!is_wp_error($page_id)) { // Save Elementor data update_post_meta($page_id, '_elementor_data', wp_slash(json_encode($layout['content']))); update_post_meta($page_id, '_elementor_edit_mode', 'builder'); update_post_meta($page_id, '_elementor_template_type', 'wp-page'); update_post_meta($page_id, '_elementor_version', '3.16.0'); echo "āœ… Created: {$city['city']} (ID: {$page_id})\n"; } } function replace_placeholders($data, $replacements) { $json = json_encode($data); foreach ($replacements as $placeholder => $value) { $json = str_replace($placeholder, $value, $json); } return json_decode($json, true); } echo "\n✨ Generation complete!\n"; COMMAND_BLOCK: <?php /** * Elementor Page Generator * Usage: php generate-elementor-pages.php */ // Load WordPress require_once('/path/to/wp-load.php'); // Load data $template = json_decode(file_get_contents('template.json'), true); $cities = json_decode(file_get_contents('cities.json'), true); foreach ($cities as $city) { // Replace placeholders in template $layout = replace_placeholders($template, [ '{{CITY_NAME}}' => $city['city'], '{{STATE}}' => $city['state'], '{{ZIP}}' => $city['zip'], '{{PHONE}}' => $city['phone'] ]); // Create page $page_id = wp_insert_post([ 'post_title' => $city['city'] . ' Services', 'post_status' => 'publish', 'post_type' => 'page', 'post_content' => '' // Elementor uses meta, not content ]); if (!is_wp_error($page_id)) { // Save Elementor data update_post_meta($page_id, '_elementor_data', wp_slash(json_encode($layout['content']))); update_post_meta($page_id, '_elementor_edit_mode', 'builder'); update_post_meta($page_id, '_elementor_template_type', 'wp-page'); update_post_meta($page_id, '_elementor_version', '3.16.0'); echo "āœ… Created: {$city['city']} (ID: {$page_id})\n"; } } function replace_placeholders($data, $replacements) { $json = json_encode($data); foreach ($replacements as $placeholder => $value) { $json = str_replace($placeholder, $value, $json); } return json_decode($json, true); } echo "\n✨ Generation complete!\n"; COMMAND_BLOCK: <?php /** * Elementor Page Generator * Usage: php generate-elementor-pages.php */ // Load WordPress require_once('/path/to/wp-load.php'); // Load data $template = json_decode(file_get_contents('template.json'), true); $cities = json_decode(file_get_contents('cities.json'), true); foreach ($cities as $city) { // Replace placeholders in template $layout = replace_placeholders($template, [ '{{CITY_NAME}}' => $city['city'], '{{STATE}}' => $city['state'], '{{ZIP}}' => $city['zip'], '{{PHONE}}' => $city['phone'] ]); // Create page $page_id = wp_insert_post([ 'post_title' => $city['city'] . ' Services', 'post_status' => 'publish', 'post_type' => 'page', 'post_content' => '' // Elementor uses meta, not content ]); if (!is_wp_error($page_id)) { // Save Elementor data update_post_meta($page_id, '_elementor_data', wp_slash(json_encode($layout['content']))); update_post_meta($page_id, '_elementor_edit_mode', 'builder'); update_post_meta($page_id, '_elementor_template_type', 'wp-page'); update_post_meta($page_id, '_elementor_version', '3.16.0'); echo "āœ… Created: {$city['city']} (ID: {$page_id})\n"; } } function replace_placeholders($data, $replacements) { $json = json_encode($data); foreach ($replacements as $placeholder => $value) { $json = str_replace($placeholder, $value, $json); } return json_decode($json, true); } echo "\n✨ Generation complete!\n"; CODE_BLOCK: php generate-elementor-pages.php CODE_BLOCK: php generate-elementor-pages.php CODE_BLOCK: php generate-elementor-pages.php CODE_BLOCK: āœ… Created: Chicago (ID: 123) āœ… Created: Boston (ID: 124) āœ… Created: Seattle (ID: 125) ✨ Generation complete! CODE_BLOCK: āœ… Created: Chicago (ID: 123) āœ… Created: Boston (ID: 124) āœ… Created: Seattle (ID: 125) ✨ Generation complete! CODE_BLOCK: āœ… Created: Chicago (ID: 123) āœ… Created: Boston (ID: 124) āœ… Created: Seattle (ID: 125) ✨ Generation complete! CODE_BLOCK: [ { "type": "et_pb_section", "attrs": { "background_color": "#ffffff" }, "content": [ { "type": "et_pb_row", "content": [ { "type": "et_pb_column", "content": [ { "type": "et_pb_text", "attrs": { "content": "<h1>{{CITY_NAME}} Professional Services</h1>" } } ] } ] } ] } ] CODE_BLOCK: [ { "type": "et_pb_section", "attrs": { "background_color": "#ffffff" }, "content": [ { "type": "et_pb_row", "content": [ { "type": "et_pb_column", "content": [ { "type": "et_pb_text", "attrs": { "content": "<h1>{{CITY_NAME}} Professional Services</h1>" } } ] } ] } ] } ] CODE_BLOCK: [ { "type": "et_pb_section", "attrs": { "background_color": "#ffffff" }, "content": [ { "type": "et_pb_row", "content": [ { "type": "et_pb_column", "content": [ { "type": "et_pb_text", "attrs": { "content": "<h1>{{CITY_NAME}} Professional Services</h1>" } } ] } ] } ] } ] COMMAND_BLOCK: <?php require_once('/path/to/wp-load.php'); $template = json_decode(file_get_contents('divi-template.json'), true); $cities = json_decode(file_get_contents('cities.json'), true); foreach ($cities as $city) { $layout = replace_placeholders($template, [ '{{CITY_NAME}}' => $city['city'], '{{STATE}}' => $city['state'] ]); $page_id = wp_insert_post([ 'post_title' => $city['city'] . ' Services', 'post_status' => 'publish', 'post_type' => 'page' ]); if (!is_wp_error($page_id)) { // Divi-specific meta update_post_meta($page_id, '_et_pb_use_builder', 'on'); update_post_meta($page_id, '_et_pb_page_layout', wp_slash(json_encode($layout))); update_post_meta($page_id, '_et_pb_old_content', ''); echo "āœ… Divi page: {$city['city']}\n"; } } COMMAND_BLOCK: <?php require_once('/path/to/wp-load.php'); $template = json_decode(file_get_contents('divi-template.json'), true); $cities = json_decode(file_get_contents('cities.json'), true); foreach ($cities as $city) { $layout = replace_placeholders($template, [ '{{CITY_NAME}}' => $city['city'], '{{STATE}}' => $city['state'] ]); $page_id = wp_insert_post([ 'post_title' => $city['city'] . ' Services', 'post_status' => 'publish', 'post_type' => 'page' ]); if (!is_wp_error($page_id)) { // Divi-specific meta update_post_meta($page_id, '_et_pb_use_builder', 'on'); update_post_meta($page_id, '_et_pb_page_layout', wp_slash(json_encode($layout))); update_post_meta($page_id, '_et_pb_old_content', ''); echo "āœ… Divi page: {$city['city']}\n"; } } COMMAND_BLOCK: <?php require_once('/path/to/wp-load.php'); $template = json_decode(file_get_contents('divi-template.json'), true); $cities = json_decode(file_get_contents('cities.json'), true); foreach ($cities as $city) { $layout = replace_placeholders($template, [ '{{CITY_NAME}}' => $city['city'], '{{STATE}}' => $city['state'] ]); $page_id = wp_insert_post([ 'post_title' => $city['city'] . ' Services', 'post_status' => 'publish', 'post_type' => 'page' ]); if (!is_wp_error($page_id)) { // Divi-specific meta update_post_meta($page_id, '_et_pb_use_builder', 'on'); update_post_meta($page_id, '_et_pb_page_layout', wp_slash(json_encode($layout))); update_post_meta($page_id, '_et_pb_old_content', ''); echo "āœ… Divi page: {$city['city']}\n"; } } COMMAND_BLOCK: <?php /** * Plugin Name: Page Generator CLI */ if (defined('WP_CLI') && WP_CLI) { WP_CLI::add_command('generate pages', 'Page_Generator_CLI'); } class Page_Generator_CLI { /** * Generate pages from template * * ## OPTIONS * * --template=<file> * : Template JSON file * * --data=<file> * : Data JSON file * * --builder=<name> * : Page builder (elementor|divi|beaver) * * ## EXAMPLES * * wp generate pages --template=template.json --data=cities.json --builder=elementor */ public function __invoke($args, $assoc_args) { $template_file = $assoc_args['template']; $data_file = $assoc_args['data']; $builder = $assoc_args['builder']; if (!file_exists($template_file)) { WP_CLI::error("Template file not found: {$template_file}"); } if (!file_exists($data_file)) { WP_CLI::error("Data file not found: {$data_file}"); } $template = json_decode(file_get_contents($template_file), true); $data = json_decode(file_get_contents($data_file), true); $generated = 0; foreach ($data as $item) { $page_id = $this->create_page($template, $item, $builder); if ($page_id) { WP_CLI::success("Created page ID {$page_id}: {$item['city']}"); $generated++; } } WP_CLI::success("Generated {$generated} pages!"); } private function create_page($template, $data, $builder) { // Replace placeholders $layout = $this->replace_placeholders($template, $data); // Create page $page_id = wp_insert_post([ 'post_title' => $data['city'] . ' Services', 'post_status' => 'publish', 'post_type' => 'page' ]); if (is_wp_error($page_id)) { return false; } // Save builder-specific meta switch ($builder) { case 'elementor': update_post_meta($page_id, '_elementor_data', wp_slash(json_encode($layout))); update_post_meta($page_id, '_elementor_edit_mode', 'builder'); break; case 'divi': update_post_meta($page_id, '_et_pb_use_builder', 'on'); update_post_meta($page_id, '_et_pb_page_layout', wp_slash(json_encode($layout))); break; case 'beaver': update_post_meta($page_id, '_fl_builder_enabled', '1'); update_post_meta($page_id, '_fl_builder_data', $layout); break; } return $page_id; } private function replace_placeholders($data, $replacements) { $json = json_encode($data); // Build replacement map $search = []; $replace = []; foreach ($replacements as $key => $value) { $search[] = '{{' . strtoupper($key) . '}}'; $replace[] = $value; } $json = str_replace($search, $replace, $json); return json_decode($json, true); } } COMMAND_BLOCK: <?php /** * Plugin Name: Page Generator CLI */ if (defined('WP_CLI') && WP_CLI) { WP_CLI::add_command('generate pages', 'Page_Generator_CLI'); } class Page_Generator_CLI { /** * Generate pages from template * * ## OPTIONS * * --template=<file> * : Template JSON file * * --data=<file> * : Data JSON file * * --builder=<name> * : Page builder (elementor|divi|beaver) * * ## EXAMPLES * * wp generate pages --template=template.json --data=cities.json --builder=elementor */ public function __invoke($args, $assoc_args) { $template_file = $assoc_args['template']; $data_file = $assoc_args['data']; $builder = $assoc_args['builder']; if (!file_exists($template_file)) { WP_CLI::error("Template file not found: {$template_file}"); } if (!file_exists($data_file)) { WP_CLI::error("Data file not found: {$data_file}"); } $template = json_decode(file_get_contents($template_file), true); $data = json_decode(file_get_contents($data_file), true); $generated = 0; foreach ($data as $item) { $page_id = $this->create_page($template, $item, $builder); if ($page_id) { WP_CLI::success("Created page ID {$page_id}: {$item['city']}"); $generated++; } } WP_CLI::success("Generated {$generated} pages!"); } private function create_page($template, $data, $builder) { // Replace placeholders $layout = $this->replace_placeholders($template, $data); // Create page $page_id = wp_insert_post([ 'post_title' => $data['city'] . ' Services', 'post_status' => 'publish', 'post_type' => 'page' ]); if (is_wp_error($page_id)) { return false; } // Save builder-specific meta switch ($builder) { case 'elementor': update_post_meta($page_id, '_elementor_data', wp_slash(json_encode($layout))); update_post_meta($page_id, '_elementor_edit_mode', 'builder'); break; case 'divi': update_post_meta($page_id, '_et_pb_use_builder', 'on'); update_post_meta($page_id, '_et_pb_page_layout', wp_slash(json_encode($layout))); break; case 'beaver': update_post_meta($page_id, '_fl_builder_enabled', '1'); update_post_meta($page_id, '_fl_builder_data', $layout); break; } return $page_id; } private function replace_placeholders($data, $replacements) { $json = json_encode($data); // Build replacement map $search = []; $replace = []; foreach ($replacements as $key => $value) { $search[] = '{{' . strtoupper($key) . '}}'; $replace[] = $value; } $json = str_replace($search, $replace, $json); return json_decode($json, true); } } COMMAND_BLOCK: <?php /** * Plugin Name: Page Generator CLI */ if (defined('WP_CLI') && WP_CLI) { WP_CLI::add_command('generate pages', 'Page_Generator_CLI'); } class Page_Generator_CLI { /** * Generate pages from template * * ## OPTIONS * * --template=<file> * : Template JSON file * * --data=<file> * : Data JSON file * * --builder=<name> * : Page builder (elementor|divi|beaver) * * ## EXAMPLES * * wp generate pages --template=template.json --data=cities.json --builder=elementor */ public function __invoke($args, $assoc_args) { $template_file = $assoc_args['template']; $data_file = $assoc_args['data']; $builder = $assoc_args['builder']; if (!file_exists($template_file)) { WP_CLI::error("Template file not found: {$template_file}"); } if (!file_exists($data_file)) { WP_CLI::error("Data file not found: {$data_file}"); } $template = json_decode(file_get_contents($template_file), true); $data = json_decode(file_get_contents($data_file), true); $generated = 0; foreach ($data as $item) { $page_id = $this->create_page($template, $item, $builder); if ($page_id) { WP_CLI::success("Created page ID {$page_id}: {$item['city']}"); $generated++; } } WP_CLI::success("Generated {$generated} pages!"); } private function create_page($template, $data, $builder) { // Replace placeholders $layout = $this->replace_placeholders($template, $data); // Create page $page_id = wp_insert_post([ 'post_title' => $data['city'] . ' Services', 'post_status' => 'publish', 'post_type' => 'page' ]); if (is_wp_error($page_id)) { return false; } // Save builder-specific meta switch ($builder) { case 'elementor': update_post_meta($page_id, '_elementor_data', wp_slash(json_encode($layout))); update_post_meta($page_id, '_elementor_edit_mode', 'builder'); break; case 'divi': update_post_meta($page_id, '_et_pb_use_builder', 'on'); update_post_meta($page_id, '_et_pb_page_layout', wp_slash(json_encode($layout))); break; case 'beaver': update_post_meta($page_id, '_fl_builder_enabled', '1'); update_post_meta($page_id, '_fl_builder_data', $layout); break; } return $page_id; } private function replace_placeholders($data, $replacements) { $json = json_encode($data); // Build replacement map $search = []; $replace = []; foreach ($replacements as $key => $value) { $search[] = '{{' . strtoupper($key) . '}}'; $replace[] = $value; } $json = str_replace($search, $replace, $json); return json_decode($json, true); } } COMMAND_BLOCK: # Generate 50 city pages wp generate pages \ --template=elementor-template.json \ --data=cities.json \ --builder=elementor # Output: # Success: Created page ID 123: Chicago # Success: Created page ID 124: Boston # Success: Created page ID 125: Seattle # Success: Generated 50 pages! COMMAND_BLOCK: # Generate 50 city pages wp generate pages \ --template=elementor-template.json \ --data=cities.json \ --builder=elementor # Output: # Success: Created page ID 123: Chicago # Success: Created page ID 124: Boston # Success: Created page ID 125: Seattle # Success: Generated 50 pages! COMMAND_BLOCK: # Generate 50 city pages wp generate pages \ --template=elementor-template.json \ --data=cities.json \ --builder=elementor # Output: # Success: Created page ID 123: Chicago # Success: Created page ID 124: Boston # Success: Created page ID 125: Seattle # Success: Generated 50 pages! COMMAND_BLOCK: <?php add_action('rest_api_init', function() { register_rest_route('page-gen/v1', '/create', [ 'methods' => 'POST', 'callback' => 'generate_page_via_api', 'permission_callback' => function() { return current_user_can('edit_pages'); } ]); }); function generate_page_via_api($request) { $params = $request->get_json_params(); $template = $params['template']; $data = $params['data']; $builder = $params['builder']; // Replace placeholders $layout = replace_placeholders($template, $data); // Create page $page_id = wp_insert_post([ 'post_title' => $data['title'], 'post_status' => 'publish', 'post_type' => 'page' ]); // Save builder meta if ($builder === 'elementor') { update_post_meta($page_id, '_elementor_data', wp_slash(json_encode($layout))); update_post_meta($page_id, '_elementor_edit_mode', 'builder'); } return new WP_REST_Response([ 'success' => true, 'page_id' => $page_id, 'url' => get_permalink($page_id) ], 201); } COMMAND_BLOCK: <?php add_action('rest_api_init', function() { register_rest_route('page-gen/v1', '/create', [ 'methods' => 'POST', 'callback' => 'generate_page_via_api', 'permission_callback' => function() { return current_user_can('edit_pages'); } ]); }); function generate_page_via_api($request) { $params = $request->get_json_params(); $template = $params['template']; $data = $params['data']; $builder = $params['builder']; // Replace placeholders $layout = replace_placeholders($template, $data); // Create page $page_id = wp_insert_post([ 'post_title' => $data['title'], 'post_status' => 'publish', 'post_type' => 'page' ]); // Save builder meta if ($builder === 'elementor') { update_post_meta($page_id, '_elementor_data', wp_slash(json_encode($layout))); update_post_meta($page_id, '_elementor_edit_mode', 'builder'); } return new WP_REST_Response([ 'success' => true, 'page_id' => $page_id, 'url' => get_permalink($page_id) ], 201); } COMMAND_BLOCK: <?php add_action('rest_api_init', function() { register_rest_route('page-gen/v1', '/create', [ 'methods' => 'POST', 'callback' => 'generate_page_via_api', 'permission_callback' => function() { return current_user_can('edit_pages'); } ]); }); function generate_page_via_api($request) { $params = $request->get_json_params(); $template = $params['template']; $data = $params['data']; $builder = $params['builder']; // Replace placeholders $layout = replace_placeholders($template, $data); // Create page $page_id = wp_insert_post([ 'post_title' => $data['title'], 'post_status' => 'publish', 'post_type' => 'page' ]); // Save builder meta if ($builder === 'elementor') { update_post_meta($page_id, '_elementor_data', wp_slash(json_encode($layout))); update_post_meta($page_id, '_elementor_edit_mode', 'builder'); } return new WP_REST_Response([ 'success' => true, 'page_id' => $page_id, 'url' => get_permalink($page_id) ], 201); } CODE_BLOCK: // Node.js example const axios = require('axios'); async function generatePages() { const template = require('./template.json'); const cities = require('./cities.json'); for (const city of cities) { const response = await axios.post( 'https://yoursite.com/wp-json/page-gen/v1/create', { template: template, data: { title: `${city.city} Services`, ...city }, builder: 'elementor' }, { auth: { username: 'admin', password: 'application-password' } } ); console.log(`āœ… Created: ${response.data.url}`); } } generatePages(); CODE_BLOCK: // Node.js example const axios = require('axios'); async function generatePages() { const template = require('./template.json'); const cities = require('./cities.json'); for (const city of cities) { const response = await axios.post( 'https://yoursite.com/wp-json/page-gen/v1/create', { template: template, data: { title: `${city.city} Services`, ...city }, builder: 'elementor' }, { auth: { username: 'admin', password: 'application-password' } } ); console.log(`āœ… Created: ${response.data.url}`); } } generatePages(); CODE_BLOCK: // Node.js example const axios = require('axios'); async function generatePages() { const template = require('./template.json'); const cities = require('./cities.json'); for (const city of cities) { const response = await axios.post( 'https://yoursite.com/wp-json/page-gen/v1/create', { template: template, data: { title: `${city.city} Services`, ...city }, builder: 'elementor' }, { auth: { username: 'admin', password: 'application-password' } } ); console.log(`āœ… Created: ${response.data.url}`); } } generatePages(); CODE_BLOCK: city,state,zip,phone,lat,lng Chicago,IL,60601,(312) 555-0100,41.8781,-87.6298 Boston,MA,02108,(617) 555-0200,42.3601,-71.0589 CODE_BLOCK: city,state,zip,phone,lat,lng Chicago,IL,60601,(312) 555-0100,41.8781,-87.6298 Boston,MA,02108,(617) 555-0200,42.3601,-71.0589 CODE_BLOCK: city,state,zip,phone,lat,lng Chicago,IL,60601,(312) 555-0100,41.8781,-87.6298 Boston,MA,02108,(617) 555-0200,42.3601,-71.0589 COMMAND_BLOCK: <?php require_once('wp-load.php'); $template = json_decode(file_get_contents('hvac-template.json'), true); $csv = array_map('str_getcsv', file('hvac-locations.csv')); $headers = array_shift($csv); foreach ($csv as $row) { $location = array_combine($headers, $row); $layout = replace_placeholders($template, [ '{{CITY}}' => $location['city'], '{{STATE}}' => $location['state'], '{{PHONE}}' => $location['phone'], '{{LAT}}' => $location['lat'], '{{LNG}}' => $location['lng'] ]); $page_id = wp_insert_post([ 'post_title' => "HVAC Services in {$location['city']}, {$location['state']}", 'post_name' => sanitize_title("hvac-{$location['city']}-{$location['state']}"), 'post_status' => 'publish', 'post_type' => 'page' ]); update_post_meta($page_id, '_elementor_data', wp_slash(json_encode($layout))); update_post_meta($page_id, '_elementor_edit_mode', 'builder'); // SEO meta update_post_meta($page_id, '_yoast_wpseo_title', "HVAC Services {$location['city']}, {$location['state']} | Company Name"); update_post_meta($page_id, '_yoast_wpseo_metadesc', "Professional HVAC services in {$location['city']}, {$location['state']}. Call {$location['phone']} today!"); echo "āœ… {$location['city']}, {$location['state']}\n"; } COMMAND_BLOCK: <?php require_once('wp-load.php'); $template = json_decode(file_get_contents('hvac-template.json'), true); $csv = array_map('str_getcsv', file('hvac-locations.csv')); $headers = array_shift($csv); foreach ($csv as $row) { $location = array_combine($headers, $row); $layout = replace_placeholders($template, [ '{{CITY}}' => $location['city'], '{{STATE}}' => $location['state'], '{{PHONE}}' => $location['phone'], '{{LAT}}' => $location['lat'], '{{LNG}}' => $location['lng'] ]); $page_id = wp_insert_post([ 'post_title' => "HVAC Services in {$location['city']}, {$location['state']}", 'post_name' => sanitize_title("hvac-{$location['city']}-{$location['state']}"), 'post_status' => 'publish', 'post_type' => 'page' ]); update_post_meta($page_id, '_elementor_data', wp_slash(json_encode($layout))); update_post_meta($page_id, '_elementor_edit_mode', 'builder'); // SEO meta update_post_meta($page_id, '_yoast_wpseo_title', "HVAC Services {$location['city']}, {$location['state']} | Company Name"); update_post_meta($page_id, '_yoast_wpseo_metadesc', "Professional HVAC services in {$location['city']}, {$location['state']}. Call {$location['phone']} today!"); echo "āœ… {$location['city']}, {$location['state']}\n"; } COMMAND_BLOCK: <?php require_once('wp-load.php'); $template = json_decode(file_get_contents('hvac-template.json'), true); $csv = array_map('str_getcsv', file('hvac-locations.csv')); $headers = array_shift($csv); foreach ($csv as $row) { $location = array_combine($headers, $row); $layout = replace_placeholders($template, [ '{{CITY}}' => $location['city'], '{{STATE}}' => $location['state'], '{{PHONE}}' => $location['phone'], '{{LAT}}' => $location['lat'], '{{LNG}}' => $location['lng'] ]); $page_id = wp_insert_post([ 'post_title' => "HVAC Services in {$location['city']}, {$location['state']}", 'post_name' => sanitize_title("hvac-{$location['city']}-{$location['state']}"), 'post_status' => 'publish', 'post_type' => 'page' ]); update_post_meta($page_id, '_elementor_data', wp_slash(json_encode($layout))); update_post_meta($page_id, '_elementor_edit_mode', 'builder'); // SEO meta update_post_meta($page_id, '_yoast_wpseo_title', "HVAC Services {$location['city']}, {$location['state']} | Company Name"); update_post_meta($page_id, '_yoast_wpseo_metadesc', "Professional HVAC services in {$location['city']}, {$location['state']}. Call {$location['phone']} today!"); echo "āœ… {$location['city']}, {$location['state']}\n"; } COMMAND_BLOCK: // Add ACF fields to generated page update_field('service_area', $location['city'], $page_id); update_field('phone_number', $location['phone'], $page_id); update_field('map_coordinates', [ 'lat' => $location['lat'], 'lng' => $location['lng'] ], $page_id); COMMAND_BLOCK: // Add ACF fields to generated page update_field('service_area', $location['city'], $page_id); update_field('phone_number', $location['phone'], $page_id); update_field('map_coordinates', [ 'lat' => $location['lat'], 'lng' => $location['lng'] ], $page_id); COMMAND_BLOCK: // Add ACF fields to generated page update_field('service_area', $location['city'], $page_id); update_field('phone_number', $location['phone'], $page_id); update_field('map_coordinates', [ 'lat' => $location['lat'], 'lng' => $location['lng'] ], $page_id); CODE_BLOCK: { "elType": "widget", "widgetType": "text-editor", "settings": { "editor": "[acf field='service_area']" } } CODE_BLOCK: { "elType": "widget", "widgetType": "text-editor", "settings": { "editor": "[acf field='service_area']" } } CODE_BLOCK: { "elType": "widget", "widgetType": "text-editor", "settings": { "editor": "[acf field='service_area']" } } COMMAND_BLOCK: <?php class Page_Generator { private $log = []; public function generate($template, $data) { foreach ($data as $item) { try { $page_id = $this->create_page($template, $item); $this->log[] = "āœ… Success: {$item['city']} (ID: {$page_id})"; } catch (Exception $e) { $this->log[] = "āŒ Error: {$item['city']} - {$e->getMessage()}"; } } // Save log file_put_contents('generation-log.txt', implode("\n", $this->log)); } private function create_page($template, $item) { $page_id = wp_insert_post([ 'post_title' => $item['city'] . ' Services', 'post_status' => 'publish', 'post_type' => 'page' ]); if (is_wp_error($page_id)) { throw new Exception($page_id->get_error_message()); } // Validate layout before saving if (!$this->validate_layout($template)) { throw new Exception('Invalid layout structure'); } $layout = $this->replace_placeholders($template, $item); update_post_meta($page_id, '_elementor_data', wp_slash(json_encode($layout))); return $page_id; } private function validate_layout($layout) { // Check required fields exist return isset($layout['content']) && is_array($layout['content']); } } COMMAND_BLOCK: <?php class Page_Generator { private $log = []; public function generate($template, $data) { foreach ($data as $item) { try { $page_id = $this->create_page($template, $item); $this->log[] = "āœ… Success: {$item['city']} (ID: {$page_id})"; } catch (Exception $e) { $this->log[] = "āŒ Error: {$item['city']} - {$e->getMessage()}"; } } // Save log file_put_contents('generation-log.txt', implode("\n", $this->log)); } private function create_page($template, $item) { $page_id = wp_insert_post([ 'post_title' => $item['city'] . ' Services', 'post_status' => 'publish', 'post_type' => 'page' ]); if (is_wp_error($page_id)) { throw new Exception($page_id->get_error_message()); } // Validate layout before saving if (!$this->validate_layout($template)) { throw new Exception('Invalid layout structure'); } $layout = $this->replace_placeholders($template, $item); update_post_meta($page_id, '_elementor_data', wp_slash(json_encode($layout))); return $page_id; } private function validate_layout($layout) { // Check required fields exist return isset($layout['content']) && is_array($layout['content']); } } COMMAND_BLOCK: <?php class Page_Generator { private $log = []; public function generate($template, $data) { foreach ($data as $item) { try { $page_id = $this->create_page($template, $item); $this->log[] = "āœ… Success: {$item['city']} (ID: {$page_id})"; } catch (Exception $e) { $this->log[] = "āŒ Error: {$item['city']} - {$e->getMessage()}"; } } // Save log file_put_contents('generation-log.txt', implode("\n", $this->log)); } private function create_page($template, $item) { $page_id = wp_insert_post([ 'post_title' => $item['city'] . ' Services', 'post_status' => 'publish', 'post_type' => 'page' ]); if (is_wp_error($page_id)) { throw new Exception($page_id->get_error_message()); } // Validate layout before saving if (!$this->validate_layout($template)) { throw new Exception('Invalid layout structure'); } $layout = $this->replace_placeholders($template, $item); update_post_meta($page_id, '_elementor_data', wp_slash(json_encode($layout))); return $page_id; } private function validate_layout($layout) { // Check required fields exist return isset($layout['content']) && is_array($layout['content']); } } - Script runs: 3 minutes - 50 pages created: Identical layouts, unique content - JSON config drives everything - Zero clicking!! - Creating 50+ similar pages (locations, products, services) - Client wants consistent layouts across all pages - Content changes frequently but structure stays same - Testing A/B variations of layouts - Migrating layouts between sites - JSON configuration (layout structure + content variables) - PHP script (reads JSON, generates page builder meta) - WP-CLI command (creates pages programmatically) - Elementor (stores layouts in postmeta _elementor_data) - Divi (stores layouts in _et_pb_page_layout) - Beaver Builder (stores layouts in _fl_builder_data) - WPBakery (stores layouts as shortcodes in post_content) - Oxygen (stores layouts in postmeta ct_builder_shortcodes) - Hero with city name - Service list - Local testimonials - Contact form with city phone - Map embed with city coordinates - Template creation: 2 hours - CSV data prep: 1 hour - Script development: 3 hours - Generation: 5 minutes - Total: 6 hours = 94 hours saved!! - 100+ pages: Minutes not days - Zero human error - Consistent layouts guaranteed - Easy bulk updates (regenerate all pages) - Client thinks you're wizard!! - Build one perfect template manually (1 hour) - Export as JSON (30 seconds) - Prepare data CSV/JSON (30 minutes) - Write generation script (2 hours) - Run script (2 minutes) - Location Sint Maartensdijk - Joined Aug 31, 2025