{"id":4672,"date":"2026-02-24T09:50:51","date_gmt":"2026-02-24T15:50:51","guid":{"rendered":"https:\/\/racmanuel.dev\/?post_type=docs&#038;p=4672"},"modified":"2026-02-24T09:50:54","modified_gmt":"2026-02-24T15:50:54","password":"","slug":"address","status":"publish","type":"docs","link":"https:\/\/racmanuel.dev\/en\/docs\/custom-fields-booster\/address\/","title":{"rendered":"Address"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">Stores a structured address as an object using an international format (V1).<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">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.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"use-cases\">Use Cases<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Collect shipping or billing-style addresses<\/li>\n\n\n\n<li>Store contact or location addresses for directories, CPTs, or users<\/li>\n\n\n\n<li>Save addresses in a structured format for integrations (ERP\/CRM\/SAP)<\/li>\n\n\n\n<li>Normalize country values using ISO2 codes<\/li>\n\n\n\n<li>Provide a formatted address string for display or search<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"field-preview\">Field Preview<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">A multi-line address form UI:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Street address (line 1)<\/li>\n\n\n\n<li>Optional street line 2<\/li>\n\n\n\n<li>City<\/li>\n\n\n\n<li>Optional state \/ province<\/li>\n\n\n\n<li>Optional postal code<\/li>\n\n\n\n<li>Country dropdown (ISO2)<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"how-to-use\">How to Use<\/h2>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Add the Address field to a Field Group.<\/li>\n\n\n\n<li>(Optional) Set <strong>Default country (ISO2)<\/strong> (example <code>MX<\/code>).<\/li>\n\n\n\n<li>Choose which optional inputs should be visible (street 2, state, postal code).<\/li>\n\n\n\n<li>Choose which inputs are required (street 1, city, country).<\/li>\n\n\n\n<li>Save the Field Group and edit a post (or render it in <code>acf_form<\/code>).<\/li>\n\n\n\n<li>No custom code is required.<\/li>\n<\/ol>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"field-settings\">Field Settings<\/h2>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><th>Setting<\/th><th>Description<\/th><th>Default<\/th><\/tr><tr><td>Default country (ISO2)<\/td><td>ISO2 code used when no country is selected<\/td><td>Empty<\/td><\/tr><tr><td>Show optional fields<\/td><td>Controls optional inputs visibility (street 2, state, postal code)<\/td><td>All enabled<\/td><\/tr><tr><td>Required fields<\/td><td>Controls required validation rules (street 1, city, country)<\/td><td>street 1 + city + country<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Notes:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Country values are stored as ISO2 codes (example <code>MX<\/code>, <code>US<\/code>).<\/li>\n\n\n\n<li>Country list is loaded from an internal JSON file (<code>countries.json<\/code>).<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"value-storage\">Value &amp; Storage<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Saved as: Post meta<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Storage type: Structured array (object)<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Return format: array (or empty array when missing\/invalid)<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><td>REST format: object<\/td><td>null<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Country format: ISO2 uppercase<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Additional field: <code>formatted<\/code> is saved automatically<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Saved structure:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>street_1<\/code> (string)<\/li>\n\n\n\n<li><code>street_2<\/code> (string)<\/li>\n\n\n\n<li><code>city<\/code> (string)<\/li>\n\n\n\n<li><code>state<\/code> (string)<\/li>\n\n\n\n<li><code>postcode<\/code> (string)<\/li>\n\n\n\n<li><code>country<\/code> (string, ISO2)<\/li>\n\n\n\n<li><code>formatted<\/code> (string, multi-line)<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Important details:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Hidden optional fields are saved as empty strings.<\/li>\n\n\n\n<li><code>formatted<\/code> is regenerated during save based on current settings and values.<\/li>\n\n\n\n<li><code>formatted<\/code> is intended for display\/search, not as a replacement for the structured fields.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"output-examples\">Output Examples<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"php-get-full-address-object\">PHP (Get full address object)<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"php\" class=\"language-php\">$address = get_field('my_address');\n\nif (is_array($address)) {\n    echo nl2br(esc_html($address['formatted'] ?? ''));\n}\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"php-access-individual-parts\">PHP (Access individual parts)<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"php\" class=\"language-php\">$address = get_field('my_address');\n\n$city    = is_array($address) ? ($address['city'] ?? '') : '';\n$country = is_array($address) ? ($address['country'] ?? '') : '';\n\necho esc_html($city . ', ' . $country);\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"twig\">Twig<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"php\" class=\"language-php\">{% set address = fn('get_field', 'my_address') %}\n{{ address.formatted|default('') }}\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"compatibility\">Compatibility<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Repeaters<\/li>\n\n\n\n<li>Flexible Content<\/li>\n\n\n\n<li>Options Pages<\/li>\n\n\n\n<li>Frontend forms (acf_form)<\/li>\n\n\n\n<li>REST API (schema, formatting, validation)<\/li>\n\n\n\n<li>Multisite<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"hooks-developer\">Hooks (Developer)<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"hooks-summary\">Hooks Summary<\/h3>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><th>Hook<\/th><th>Type<\/th><th>Purpose<\/th><\/tr><tr><td>custom_fields_booster_address_defaults<\/td><td>Filter<\/td><td>Modify default settings and placeholders.<\/td><\/tr><tr><td>custom_fields_booster_address_supports<\/td><td>Filter<\/td><td>Modify ACF support flags.<\/td><\/tr><tr><td>custom_fields_booster_address_before_settings<\/td><td>Action<\/td><td>Run logic before rendering settings UI.<\/td><\/tr><tr><td>custom_fields_booster_address_after_settings<\/td><td>Action<\/td><td>Run logic after rendering settings UI.<\/td><\/tr><tr><td>custom_fields_booster_address_before_enqueue<\/td><td>Action<\/td><td>Run logic before enqueuing assets.<\/td><\/tr><tr><td>custom_fields_booster_address_after_enqueue<\/td><td>Action<\/td><td>Run logic after enqueuing assets.<\/td><\/tr><tr><td>custom_fields_booster_address_before_render<\/td><td>Action<\/td><td>Run logic before rendering UI.<\/td><\/tr><tr><td>custom_fields_booster_address_after_render<\/td><td>Action<\/td><td>Run logic after rendering UI.<\/td><\/tr><tr><td>custom_fields_booster_address_update_value<\/td><td>Filter<\/td><td>Modify the value before saving.<\/td><\/tr><tr><td>custom_fields_booster_address_load_value<\/td><td>Filter<\/td><td>Modify the value after loading.<\/td><\/tr><tr><td>custom_fields_booster_address_validate_value<\/td><td>Filter<\/td><td>Modify validation result.<\/td><\/tr><tr><td>custom_fields_booster_address_format_value<\/td><td>Filter<\/td><td>Modify value returned by <code>get_field()<\/code>.<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"filters\">Filters<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"defaults\">Defaults<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Filter:<\/strong> <code>custom_fields_booster_address_defaults<\/code><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Purpose: Override default placeholders, required flags, and visible fields.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">When: You want consistent defaults across all Address fields.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"php\" class=\"language-php\">add_filter('custom_fields_booster_address_defaults', function ($defaults) {\n    $defaults['default_country'] = 'MX';\n    $defaults['require_country'] = 1;\n    $defaults['show_postcode'] = 0;\n    return $defaults;\n});\n<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"supports\">Supports<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Filter:<\/strong> <code>custom_fields_booster_address_supports<\/code><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Purpose: Control ACF supports such as required or escaping behavior.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">When: Your project needs different support flags.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"php\" class=\"language-php\">add_filter('custom_fields_booster_address_supports', function ($supports) {\n    $supports['required'] = false;\n    return $supports;\n});\n<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"update-value\">Update Value<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Filter:<\/strong> <code>custom_fields_booster_address_update_value<\/code><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Purpose: Modify the sanitized structured address before it is saved.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">When: You need normalization, enrichment, or compatibility transformations.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"php\" class=\"language-php\">add_filter('custom_fields_booster_address_update_value', function ($out, $post_id, $field) {\n    if (!empty($out['country'])) {\n        $out['country'] = strtolower($out['country']);\n    }\n\n    return $out;\n}, 10, 3);\n<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"load-value\">Load Value<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Filter:<\/strong> <code>custom_fields_booster_address_load_value<\/code><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Purpose: Modify the value after loading from storage.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">When: You want to normalize missing keys or apply defaults on load.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"php\" class=\"language-php\">add_filter('custom_fields_booster_address_load_value', function ($value, $post_id, $field) {\n    return is_array($value) ? $value : array();\n}, 10, 3);\n<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"validate-value\">Validate Value<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Filter:<\/strong> <code>custom_fields_booster_address_validate_value<\/code><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Purpose: Modify the validation result.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">When: You need custom validation logic.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"php\" class=\"language-php\">add_filter('custom_fields_booster_address_validate_value', function ($valid, $value, $field, $input) {\n    return $valid;\n}, 10, 4);\n<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"format-value-return\">Format Value (Return)<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Filter:<\/strong> <code>custom_fields_booster_address_format_value<\/code><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Purpose: Modify value returned by <code>get_field()<\/code> and REST output formatting.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">When: You want to normalize missing keys or add computed keys.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"php\" class=\"language-php\">add_filter('custom_fields_booster_address_format_value', function ($value, $post_id, $field) {\n    $value = is_array($value) ? $value : array();\n\n    $value += array(\n        'street_1' =&gt; '',\n        'street_2' =&gt; '',\n        'city' =&gt; '',\n        'state' =&gt; '',\n        'postcode' =&gt; '',\n        'country' =&gt; '',\n        'formatted' =&gt; '',\n    );\n\n    return $value;\n}, 10, 3);\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"actions\">Actions<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"before-render\">Before Render<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Action:<\/strong> <code>custom_fields_booster_address_before_render<\/code><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Runs before rendering the field UI and provides the countries dataset.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"php\" class=\"language-php\">add_action('custom_fields_booster_address_before_render', function ($field, $countries) {\n    \/\/ Pre-render logic.\n}, 10, 2);\n<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"after-render\">After Render<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Action:<\/strong> <code>custom_fields_booster_address_after_render<\/code><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Runs after rendering the field UI and provides the countries dataset.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"php\" class=\"language-php\">add_action('custom_fields_booster_address_after_render', function ($field, $countries) {\n    \/\/ Post-render logic.\n}, 10, 2);\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"assets\">Assets<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">This field enqueues styles whenever the input is rendered (admin and frontend via <code>acf_form()<\/code>):<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>admin\/css\/cfb-field-address.css<\/code><\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"rest-api\">REST API<\/h2>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><td>Schema: object<\/td><td>null<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Properties: <code>street_1<\/code>, <code>street_2<\/code>, <code>city<\/code>, <code>state<\/code>, <code>postcode<\/code>, <code>country<\/code>, <code>formatted<\/code><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Notes: <code>formatted<\/code> is included in REST output when available.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Example REST output:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"php\" class=\"language-php\">{\n  \"my_address\": {\n    \"street_1\": \"Av. Siempre Viva 742\",\n    \"street_2\": \"Depto 4B\",\n    \"city\": \"Merida\",\n    \"state\": \"Yucatan\",\n    \"postcode\": \"97000\",\n    \"country\": \"MX\",\n    \"formatted\": \"Av. Siempre Viva 742\\nDepto 4B\\nMerida, Yucatan, 97000\\nMX\"\n  }\n}\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"rest-validation\">REST Validation<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>null<\/code> is allowed.<\/li>\n\n\n\n<li>Non-array values are rejected with a validation error message.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"security-escaping\">Security &amp; Escaping<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Values are sanitized on save using <code>sanitize_text_field()<\/code>.<\/li>\n\n\n\n<li>Country codes are normalized to uppercase.<\/li>\n\n\n\n<li>Output should be escaped in templates (<code>esc_html<\/code>, <code>nl2br<\/code>, etc.).<\/li>\n\n\n\n<li><code>escaping_html<\/code> support is set to false to avoid unwanted transformations in structured values.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"notes-limitations\">Notes \/ Limitations<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li>This field stores a structured value, not a single string.<\/li>\n\n\n\n<li><code>formatted<\/code> is generated at save time and depends on visibility settings.<\/li>\n\n\n\n<li>Hidden optional fields are saved as empty strings.<\/li>\n\n\n\n<li>Country list depends on the internal <code>countries.json<\/code> dataset and must contain ISO2 codes.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"changelog\">Changelog<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li>1.0.0 \u2014 Initial release<\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>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 Field Preview A multi-line address form UI: How to Use Field Settings Setting Description Default [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"_acf_changed":false,"_gspb_post_css":"","_glsr_average":0,"_glsr_ranking":0,"_glsr_reviews":0,"footnotes":""},"doc_category":[96],"doc_tag":[102],"class_list":["post-4672","docs","type-docs","status-publish","hentry","doc_category-custom-fields-booster","doc_tag-free"],"blocksy_meta":[],"year_month":"2026-06","word_count":1047,"total_views":0,"reactions":{"happy":0,"normal":0,"sad":0},"author_info":{"name":"racmanuel","author_nicename":"ra_cm","author_url":"https:\/\/racmanuel.dev\/en\/author\/ra_cm\/"},"doc_category_info":[{"term_name":"Custom Fields Booster","term_url":"https:\/\/racmanuel.dev\/en\/docs\/category\/custom-fields-booster\/"}],"doc_tag_info":[{"term_name":"Free","term_url":"https:\/\/racmanuel.dev\/en\/docs\/tag\/free\/"}],"acf":[],"_links":{"self":[{"href":"https:\/\/racmanuel.dev\/en\/wp-json\/wp\/v2\/docs\/4672","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/racmanuel.dev\/en\/wp-json\/wp\/v2\/docs"}],"about":[{"href":"https:\/\/racmanuel.dev\/en\/wp-json\/wp\/v2\/types\/docs"}],"author":[{"embeddable":true,"href":"https:\/\/racmanuel.dev\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/racmanuel.dev\/en\/wp-json\/wp\/v2\/comments?post=4672"}],"version-history":[{"count":1,"href":"https:\/\/racmanuel.dev\/en\/wp-json\/wp\/v2\/docs\/4672\/revisions"}],"predecessor-version":[{"id":4673,"href":"https:\/\/racmanuel.dev\/en\/wp-json\/wp\/v2\/docs\/4672\/revisions\/4673"}],"wp:attachment":[{"href":"https:\/\/racmanuel.dev\/en\/wp-json\/wp\/v2\/media?parent=4672"}],"wp:term":[{"taxonomy":"doc_category","embeddable":true,"href":"https:\/\/racmanuel.dev\/en\/wp-json\/wp\/v2\/doc_category?post=4672"},{"taxonomy":"doc_tag","embeddable":true,"href":"https:\/\/racmanuel.dev\/en\/wp-json\/wp\/v2\/doc_tag?post=4672"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}