Turning Static HTML Elements into Advanced Custom Fields, the fast way

June 15, 2023


The Problem

If there is one thing that every developer hates, it's repeating the same task twice. I recently found myself in the scenario where I wasn't only repeating the same task twice, I was repeating it over and over again. I'm talking about turning text elements on a page into advanced custom fields on a page in a WordPress backend.

If you read my last post, you know that we've been doing a lot of headless WordPress work at Tattoo Projects. While there are quite a few things that I like about headless WordPress, there's also quite a few things I dislike (I'm currently writing this post in Hygraph for my own blog, if that tells you anything). One of those things is that our clients often want control over all the copy on every page.

I've been working on a new Sveltekit template that allows admins to edit any text on a webpage in real time on the page itself, but it's not quite ready, or battle tested yet. In the meantime, we've been creating pages in the WordPress dashboard, creating a custom field for every text element on the page in our frontend, and binding the two together through WPGraphQL. If you've ever done something like this, you now that it takes a lot of time. You have to go through every page and create text custom fields that match. It's slow, and I wanted a better way.

The Solution

I decided to take this opportunity to create a CLI with node. I've created CLIs in other languages like bash or python, and I want to build one in Rust soon, but I'm currently most proficient in JavaScript, and I already had a particular node module dependency for this tool in mind. I went ahead and created a new node project and began to build my functionality.

HTML-To-ACF uses a pretty simple approach when it comes to solving my problem. You feed it a URL, a page name, and optionally, an element to fetch text from (in the case you have a footer or nav component you don't want scraped), and then hit go. Like so:

htmltoacf -u "http://localhost/" -p "home" -i "page-content"

This will result in spitting out a JSON object that you can drop into the importer within ACF in the WordPress dashboard. It will create a field group called "home" and the output is already ready to go for WPGraphQL, making it easily queriable. The only additional step you need to take is creating a page to bind the field group to, and you're off to the races.

If you want to use this tool yourself, I've published it to my organization's NPM feed. Simply run the following:

npm i htmltoacf -g

Once it's installed, you should have the htmltoacf command available to you. If you ever forget how it works, or want to see the options, you can run htmtoacf --help or htmltoacf info

Future Plans

If you use this tool, you'll see that it can save you a ton of time, but it also involves the steps of importing the JSON it spits out for ACF and setting up the pages that field groups get mapped to. I would like to continue working on this and eventually add additional arguments that allow a user to feed the CLI a WP endpoint that automatically scrapes HTML page(s) and imports each one into WP, followed up by page creation. Basically a magic button to save tons of time.

I've also opened up the repo to the public for any PRs or bug fixes. I want this to be open source because I threw it together quickly to solve a problem I was having, but there are likely ways for it to be optimized. If you'd like to contribute, open up a pr on our repo.

In the meantime, hopefully this little CLI will help save someone some time. I have also put together a way to add page builder functionality to headless WordPress instances to introduce an even more powerful way to solve this problem, and should have an article on that soon. Happy hacking!