WordPress Automation
Building a Reliable WordPress Category FAQ Automation with Browser automation software, ACF, and TinyMCE
Updating dozens of WooCommerce product categories manually is slow, repetitive, and error‑prone. When each category contains an ACF WYSIWYG field powered by TinyMCE, the process becomes even more tedious. We wanted a solution that could take structured FAQ content from an AI generated (Human edited) CSV file and automatically inject it into the correct category pages inside WordPress — safely, reliably, and at scale.
This article walks through how we engineered a fully modular, production‑ready automation system using Browser automation software, JavaScript ES modules, and a deep understanding of how WordPress, WooCommerce, ACF, and TinyMCE behave under automation.
The Challenge: Automating a Hostile UI
WordPress admin pages are not designed for automation. WooCommerce taxonomy pages load slowly, ACF fields sync asynchronously, and TinyMCE hides the underlying textarea when in Visual mode. On top of that, WordPress doesn’t always redirect after saving a category — sometimes it simply displays a “Category updated” message and waits for user input.
The automation needed to:
- Log into WordPress securely
- Parse a CSV containing category names and FAQ HTML
- Navigate to the correct category
- Switch TinyMCE into Text mode
- Inject HTML into the ACF WYSIWYG field
- Trigger ACF’s hidden field sync
- Submit the form in a “trusted” way
- Detect the success message
- Return to the category list
- Repeat for all categories
This required a careful blend of DOM events, Browser automation software navigation control, and defensive coding.
Step 1: Parsing the CSV
The CSV contained rows like:
Code
1,”Premium Office Furniture Brands”,”<p>FAQ HTML here…</p>”
We cleaned doubled quotes, extracted each record with a regex, and produced a structured array:
js
[
{ id: “1”, category: “Premium Office Furniture Brands”, faqHtml: “<p>…</p>” },
…
]
This gave us clean, predictable input for the automation.
Step 2: Logging into WordPress
Browser automation software handled the login flow:
- Navigate to /admin
- Fill username and password
- Submit the form
- Wait for the admin dashboard
We added a verification step to ensure the login succeeded before continuing.
Step 3: Navigating to the Category List
WooCommerce’s category list lives at:
Code
/wp-admin/edit-tags.php?taxonomy=product_cat&post_type=product&show_all_terms=1
We built a dedicated function to load this page and wait for the category table to appear. This became the “home base” for each iteration.
Step 4: Finding the Correct Category
WordPress category names can contain inconsistent spacing, so we normalised the input and used Browser automation software’s hasText filter to locate the exact row.
Once found, we clicked the category using a real DOM click, not Browser automation software’s synthetic click. This bypassed WordPress’s hover‑based UI quirks.
Step 5: Handling TinyMCE and ACF
This was the hardest part.
TinyMCE hides the textarea when content exists
If the field already contains text, TinyMCE loads in Visual mode:
- The iframe is visible
- The textarea is hidden (aria-hidden=”true”)
- Waiting for the textarea to be “visible” causes a timeout
Solution: Always switch to Text mode
We clicked the “Text” tab using a DOM click. This reliably reveals the textarea regardless of initial state.
Injecting the FAQ HTML
Once in Text mode, we filled the textarea directly.
Triggering ACF’s hidden field sync
ACF stores WYSIWYG content in a hidden input:
Code
acf[field_xxx]
Filling the textarea alone does not update this hidden field. We dispatched input and change events manually, then waited until the hidden field contained the new HTML.
This was the key to making the FAQ actually save.
Step 6: Submitting the Form
WordPress sometimes ignores synthetic clicks. We fired:
- a trusted MouseEvent(‘click’)
- a trusted submit event
- and finally form.submit()
This guaranteed the form POST was processed.
Step 7: Handling WordPress’s “Category updated” Message
WordPress does not always redirect after saving a category. Instead, it shows:
Category updated. ← Go to Categories
Rather than relying on this link, we built a deterministic flow:
- Wait for the success message
- Navigate back to the category list URL explicitly
- Wait for the table to load
- Continue the loop
This eliminated navigation race conditions and timeouts.
Step 8: Modularising the Entire System
Once the automation was stable, we split it into clean modules:
Code
src/
login.js
loadCsv.js
goToCategoryList.js
findCategoryRow.js
updateCategoryFaq.js
returnToCategoryList.js
main.js
Each module does one job well. This makes the system:
- maintainable
- testable
- extendable
- production‑ready
The Result
We built a robust automation that:
- logs into WordPress
- reads structured FAQ content
- updates each category safely
- handles TinyMCE and ACF correctly
- avoids race conditions
- works whether fields are empty or already populated
- scales to all 90 categories
This is the kind of automation that saves hours if not days of manual work, eliminates human error, and gives you a repeatable workflow you can run anytime.
- We then added a module to enter the JSON‑LD FAQPage schema injection
Where to go next
Now that the core automation is modular and stable, we can easily add:
- Skip‑if‑already‑updated logic
- Logging and reporting
- Retry logic for slow WP admin pages
- Batch processing for multiple CSV files