
In a recent project, I had to bulk-import postcode data into a WordPress site using Advanced Custom Fields (ACF). Each postcode had to be linked to a custom taxonomy term (location
), and each term had a repeater field named postcode_area_coverage
, which stores multiple entries under a subfield called code
.
The data came from a simple CSV file provided by the business manager. Instead of manually entering data term by term, I wrote a script that matched postcodes to taxonomy terms based on email addresses and updated everything programmatically.
The Data Format
The CSV I received looked like this:
EH1,,branch1@email.com
EH2,,branch1@email.com
AB10,,branch2@email.com
The logic was straightforward: match each postcode to the correct location using the associated email, then populate the repeater field accordingly.
I wrote a PHP script that handled the following:
- Loaded all
location
terms from the taxonomy. - Built a reference map using each term’s ACF
email
field. - Read the CSV file row by row.
- Matched each row’s email to a location term.
- Grouped the postcodes by term ID.
- Updated the
postcode_area_coverage
repeater usingupdate_field()
.
The Code.
<?php
include('wp-load.php'); // adjust path as needed to load WordPress context
$location_ref = [];
$taxonomy = 'location';
// Step 1: Build reference map of emails to term IDs
$locations = get_terms([
'taxonomy' => $taxonomy,
'hide_empty' => false,
]);
if (!empty($locations) && !is_wp_error($locations)) {
foreach ($locations as $location) {
$email_field = get_field('email', 'location_' . $location->term_id);
if ($email_field) {
$location_ref[trim($email_field)] = [
'term' => $location->term_id,
'email' => trim($email_field)
];
}
}
}
$postcodes_csv = 'postcode.csv'; // path to your CSV file
$data_array = [];
$orphan_postcode = [];
if (($fh = fopen($postcodes_csv, 'r')) !== false) {
while (($data = fgetcsv($fh, 1000, ',')) !== false) {
$postcode = trim($data[0] ?? '');
$email = trim($data[2] ?? '');
if ($postcode) {
if ($email && isset($location_ref[$email])) {
$term_id = $location_ref[$email]['term'];
$data_array[$term_id][] = ['code' => $postcode]; // 'code' is the ACF subfield
} else {
$orphan_postcode[] = $postcode;
}
}
}
fclose($fh);
}
// Step 2: Update each term’s repeater field
foreach ($data_array as $term_id => $postcodes) {
update_field('postcode_area_coverage', $postcodes, $taxonomy . '_' . $term_id);
}
// Optional: Printing orphan postcodes for debugging
if (!empty($orphan_postcode)) {
echo "Postcodes with no matching email:<br>";
echo implode(', ', $orphan_postcode);
}
What This Does
- Reads the CSV line by line.
- Trims and sanitises inputs to avoid matching issues.
- Maps each row to the correct taxonomy term using the
email
ACF field. - Builds an array in ACF repeater format (
[ ['code' => 'EH1'], ... ]
). - Uses
update_field()
to push postcode data into each term.
Why I Like This Approach
- It’s fast and scalable.
- It makes use of existing ACF structures — no custom database tables or plugins needed.
- It’s repeatable: anytime the business updates postcode data, I just run the script again.
This was a small but satisfying piece of dev work — a perfect example of automating the boring stuff. If you’re working with taxonomy terms, ACF, or bulk content in WordPress, scripting these kinds of updates can save hours of time and prevent manual errors.
Leave a Reply