Address
5 min read
Stores a structured address as an object using an international format (V1).
The field renders multiple inputs (street, city, state, postal code, country) and saves a single structured value, including a pre-built formatted string for display or search.
Use Cases #
- Collect shipping or billing-style addresses (without WooCommerce dependency)
- Store contact or location addresses for directories, CPTs, or users
- Save addresses in a structured format for integrations (ERP/CRM/SAP)
- Normalize country values using ISO2 codes
- Provide a ready-to-use
formattedaddress string for display and search
Field Preview #
A multi-line address form UI:
- Street address (line 1)
- Optional street line 2
- City
- Optional state / province
- Optional postal code
- Country dropdown (ISO2)
How to Use #
- Add the Address field to a Field Group
- Optionally set Default country (ISO2) (example
MX) - Choose which optional inputs should be visible (street 2, state, postal code)
- Choose which inputs are required (street 1, city, country)
- Save the Field Group and edit a post (or render it in
acf_form)
No custom code is required.
Field Settings #
| Setting | Description | Default |
|---|---|---|
| Default country (ISO2) | ISO2 code used when no country is selected | Empty |
| Show optional fields | Controls optional inputs visibility (street 2, state, postal code) | All enabled |
| Required fields | Controls required validation rules (street 1, city, country) | street 1 + city + country |
Notes:
- Country values are stored as ISO2 codes (example
MX,US) - Country list is loaded from an internal JSON file (
countries.json)
Value & Storage #
- Saved as: Post meta
- Storage type: Structured array (object)
- Return format:
array(or empty array when missing/invalid) - REST format:
object | null - Country format: ISO2 uppercase
- Additional field:
formattedis saved automatically
Saved structure:
street_1(string)street_2(string)city(string)state(string)postcode(string)country(string, ISO2)formatted(string, multi-line)
Important details:
- Hidden optional fields are saved as empty strings
formattedis regenerated during save based on current settings and valuesformattedis intended for display/search, not as a replacement for the structured fields
Output Examples #
PHP (Get full address object) #
$address = get_field('my_address');
if (is_array($address)) {
// Example: show formatted address.
echo nl2br(esc_html($address['formatted'] ?? ''));
}
PHP (Access individual parts) #
$address = get_field('my_address');
$city = is_array($address) ? ($address['city'] ?? '') : '';
$country = is_array($address) ? ($address['country'] ?? '') : '';
echo esc_html($city . ', ' . $country);
Twig #
{% set address = fn('get_field', 'my_address') %}
{{ address.formatted|default('') }}
Compatibility #
- Repeaters
- Flexible Content
- Options Pages
- Frontend forms (
acf_form) - REST API (schema, formatting, validation)
- Multisite
Hooks (Developer) #
Hooks Summary #
| Hook | Type | Purpose |
|---|---|---|
cfb/field/address/defaults | Filter | Modify default settings and placeholders |
cfb/field/address/supports | Filter | Modify ACF support flags |
cfb/field/address/before_render | Action | Run logic before rendering UI |
cfb/field/address/after_render | Action | Run logic after rendering UI |
cfb/field/address/update_value | Filter | Modify the value before saving |
cfb/field/address/format_value | Filter | Modify value returned by get_field() |
Filters #
Defaults #
Filter: cfb/field/address/defaults
Purpose: Override default placeholders, required flags, and visible fields
When: You want consistent defaults across all Address fields
add_filter('cfb/field/address/defaults', function ($defaults) {
$defaults['default_country'] = 'MX';
$defaults['require_country'] = 1;
$defaults['show_postcode'] = 0;
return $defaults;
});
Supports #
Filter: cfb/field/address/supports
Purpose: Control ACF supports such as required or escaping behavior
When: Your project needs different support flags
add_filter('cfb/field/address/supports', function ($supports) {
$supports['required'] = false;
return $supports;
});
Update Value #
Filter: cfb/field/address/update_value
Purpose: Modify the sanitized structured address before it is saved
When: You need normalization, enrichment, or compatibility transformations
add_filter('cfb/field/address/update_value', function ($out, $post_id, $field) {
// Example: store country as lowercase for an external system
if (!empty($out['country'])) {
$out['country'] = strtolower($out['country']);
}
return $out;
}, 10, 3);
Format Value (Return) #
Filter: cfb/field/address/format_value
Purpose: Modify value returned by get_field() and REST output formatting
When: You want to normalize missing keys or add computed keys
add_filter('cfb/field/address/format_value', function ($value, $post_id, $field) {
// Example: guarantee keys exist
$value = is_array($value) ? $value : array();
$value += array(
'street_1' => '',
'street_2' => '',
'city' => '',
'state' => '',
'postcode' => '',
'country' => '',
'formatted' => '',
);
return $value;
}, 10, 3);
Actions #
Before Render #
Action: cfb/field/address/before_render
Runs before rendering the field UI and provides the countries dataset
Useful for custom UI injections, debugging, or dynamic behavior.
add_action('cfb/field/address/before_render', function ($field, $countries) {
// Pre-render logic
}, 10, 2);
After Render #
Action: cfb/field/address/after_render
Runs after rendering the field UI and provides the countries dataset.
add_action('cfb/field/address/after_render', function ($field, $countries) {
// Post-render logic
}, 10, 2);
Assets #
This field enqueues styles whenever the input is rendered (admin and frontend via acf_form()):
admin/css/cfb-field-address.css
REST API #
- Schema:
object | null - Properties:
street_1,street_2,city,state,postcode,country,formatted - Notes:
formattedis included in REST output when available
Example REST output:
{
"my_address": {
"street_1": "Av. Siempre Viva 742",
"street_2": "Depto 4B",
"city": "Mérida",
"state": "Yucatán",
"postcode": "97000",
"country": "MX",
"formatted": "Av. Siempre Viva 742\nDepto 4B\nMérida, Yucatán, 97000\nMX"
}
}
REST Validation #
nullis allowed- Non-array values are rejected with a validation error message
- Required rules (street 1, city, country) are validated through standard field validation when saving via normal ACF flows
Security & Escaping #
- Values are sanitized on save using
sanitize_text_field() - Country codes are normalized to uppercase
- Output should be escaped in templates (
esc_html,nl2br, etc.) escaping_htmlsupport is set tofalseto avoid unwanted transformations in structured values
Notes / Limitations #
- This field stores a structured value, not a single string
formattedis generated at save time and depends on visibility settings- Hidden optional fields are saved as empty strings
- Country list depends on the internal
countries.jsondataset and must contain ISO2 codes
Changelog #
- 1.0.0 — Initial release