ACF Custom Fields Setup: From Prototype to Production
Imagine: an editor needs to fill a product card with 50 parameters. Standard metaboxes force them to scroll through an endless list of text fields. Errors are inevitable: mangled dates, broken links, swapped numbers. We integrated Advanced Custom Fields with field groups and nested repeaters—entry speed tripled, errors dropped to zero. The editor gets clear forms, while the code stays clean and maintainable. A typical project with 10 field groups takes 4–6 hours instead of 10–15 when done manually—a 2–3x difference. Order turnkey ACF setup and accelerate content entry.
Uncomfortable data entry is a classic pain point. Standard WordPress meta boxes are text fields without hints. The editor makes mistakes in date format, URLs, numbers. ACF provides a calendar, sliders, dropdowns. Support complexity is also solved: when there are many fields, code with add_meta_box and update_post_meta turns into spaghetti. ACF groups fields, supports conditional logic and JSON sync. Flexible Content lets the editor assemble a page from blocks (hero, text, gallery). We set up the logic once; the editor uses it for years.
What problems we solve with ACF
- Inconvenient data entry. ACF replaces text fields with calendar, sliders, dropdowns. No more format errors.
- Complex maintenance. Field grouping, conditional display, and JSON sync simplify code support.
- Flexibility without programming. Flexible Content gives the editor the ability to build a page from predefined blocks without PHP knowledge.
| Criteria | ACF | Manual meta boxes |
|---|---|---|
| Setup time for 10 fields | 2–4 hours | 6–8 hours |
| Editor experience | High (UI field types) | Low (plain text) |
| Query performance | Medium (100+ fields may slow down) | Depends on implementation |
| Development speed | 2–3x faster | Slower |
How ACF simplifies editor work?
We register field groups programmatically—this is the production standard. The code lives in the theme and is versioned in Git. Example group "Project Details":
add_action('acf/init', function () {
acf_add_local_field_group([
'key' => 'group_project_details',
'title' => 'Детали проекта',
'fields' => [
[
'key' => 'field_project_client',
'label' => 'Клиент',
'name' => 'project_client',
'type' => 'text',
'required' => 1,
'placeholder' => 'Название компании',
],
[
'key' => 'field_project_year',
'label' => 'Год реализации',
'name' => 'project_year',
'type' => 'number',
'min' => 2000,
'max' => 2030,
'default_value' => date('Y'),
],
[
'key' => 'field_project_url',
'label' => 'URL проекта',
'name' => 'project_url',
'type' => 'url',
],
[
'key' => 'field_project_tech_stack',
'label' => 'Технологии',
'name' => 'project_tech_stack',
'type' => 'checkbox',
'choices' => [
'react' => 'React',
'vue' => 'Vue.js',
'laravel' => 'Laravel',
'wordpress' => 'WordPress',
'nextjs' => 'Next.js',
],
'layout' => 'horizontal',
],
[
'key' => 'field_project_gallery',
'label' => 'Галерея скриншотов',
'name' => 'project_gallery',
'type' => 'gallery',
'min' => 0,
'max' => 20,
'mime_types' => 'jpg,jpeg,png,webp',
'return_format' => 'array',
],
],
'location' => [
[['param' => 'post_type', 'operator' => '==', 'value' => 'project']],
],
'menu_order' => 0,
'position' => 'normal',
'style' => 'seamless',
'label_placement' => 'top',
]);
});
Why register fields via code instead of the admin UI?
The ACF admin UI is convenient for quick prototypes, but in production leads to problems: configuration is stored in the database, hard to version, and fields can disappear on migration. Code is the only reliable method. The ACF documentation recommends this approach for production.
Repeater—repeatable data blocks
[
'key' => 'field_project_results',
'label' => 'Результаты проекта',
'name' => 'project_results',
'type' => 'repeater',
'min' => 1,
'max' => 10,
'layout' => 'table',
'button_label' => 'Добавить результат',
'sub_fields' => [
['key' => 'field_result_metric', 'label' => 'Метрика', 'name' => 'metric', 'type' => 'text', 'placeholder' => 'Конверсия'],
['key' => 'field_result_before', 'label' => 'До', 'name' => 'before', 'type' => 'text', 'placeholder' => '1.2%'],
['key' => 'field_result_after', 'label' => 'После', 'name' => 'after', 'type' => 'text', 'placeholder' => '3.8%'],
],
],
Output data on the frontend: get_sub_field in a have_rows loop. We use the code below in project templates.
if (have_rows('project_results')) {
echo '<table class="results-table">';
echo '<thead><tr><th>Метрика</th><th>До</th><th>После</th></tr></thead><tbody>';
while (have_rows('project_results')) {
the_row();
printf('<tr><td>%s</td><td>%s</td><td>%s</td></tr>',
esc_html(get_sub_field('metric')),
esc_html(get_sub_field('before')),
esc_html(get_sub_field('after'))
);
}
echo '</tbody></table>';
}
Flexible Content—page builder
Allows the editor to assemble a page from different block types: hero, text, columns. We prepare the layouts, and the editor fills them with content.
[
'key' => 'field_page_sections',
'label' => 'Секции страницы',
'name' => 'page_sections',
'type' => 'flexible_content',
'button_label' => 'Добавить секцию',
'layouts' => [
'hero' => [
'key' => 'layout_hero',
'name' => 'hero',
'label' => 'Hero-баннер',
'sub_fields' => [
['key' => 'field_hero_title', 'label' => 'Заголовок', 'name' => 'title', 'type' => 'text'],
['key' => 'field_hero_bg', 'label' => 'Фон', 'name' => 'bg', 'type' => 'image', 'return_format' => 'array'],
['key' => 'field_hero_button', 'label' => 'Кнопка', 'name' => 'button', 'type' => 'link'],
],
],
'text_columns' => [
'key' => 'layout_text_columns',
'name' => 'text_columns',
'label' => 'Текст в колонках',
'sub_fields' => [
['key' => 'field_tc_cols', 'label' => 'Колонки', 'name' => 'columns', 'type' => 'repeater',
'sub_fields' => [
['key' => 'field_tc_text', 'name' => 'text', 'label' => 'Текст', 'type' => 'wysiwyg'],
],
],
],
],
],
],
Conditional field display
ACF allows showing a field only when another field has a specific value. For example, show a CTA button text only if the toggle is enabled.
[
'key' => 'field_show_cta',
'label' => 'Показать CTA',
'name' => 'show_cta',
'type' => 'true_false',
'ui' => 1,
],
[
'key' => 'field_cta_text',
'label' => 'Текст кнопки',
'name' => 'cta_text',
'type' => 'text',
'conditional_logic' => [
[['field' => 'field_show_cta', 'operator' => '==', 'value' => '1']],
],
],
JSON sync
ACF PRO automatically saves field groups to files /acf-json/*.json when modified via the admin UI. We commit these files to Git, and on another environment we click Sync. For automation, we use acf_sync_field_groups() in a must-use plugin.
Common mistakes and how to avoid them
- Empty fields after saving—often due to missing
get_field()check: always useget_field('name', $post_id) ?: 'default'. - Forgotten fields in templates—check with
have_rows()orget_field()with a fallback. - Incorrect data type—ACF does not validate automatically; use
esc_*functions.
| Field type | Average load time per page (10 fields) | Recommendations |
|---|---|---|
| Text | 2ms | No restrictions |
| Image | 50ms (with 5 images) | Use return_format => 'id' and lazy loading |
| Gallery | 100ms (10 images) | Cache or output via AJAX |
| Repeater (10 rows) | 20ms | Use get_field() instead of have_rows() for large sets |
| Flexible Content (5 blocks) | 40ms | Group layouts and cache results |
What is included in turnkey work
- Audit of current meta fields and post types.
- Design of ACF field structure for your tasks.
- Programmatic registration of all field groups in functions.php or a separate plugin.
- Setup of repeaters, flexible content, conditional logic, and options pages.
- Creation of frontend output templates.
- Export of configuration to JSON and sync setup.
- Documentation of fields and their usage.
- Performance testing and query optimization if needed.
- Editor training (basic).
Process of work
- Analysis. We study content types, current meta fields, and editor needs.
- Design. We create a layout of field groups: types, relations, conditional displays.
- Implementation. We code field registration and output. Using PHP 8.x, Composer, modern practices.
- Testing. We test all scenarios: creation, editing, output, caching.
- Deployment. Sync via JSON, pass documentation.
Timeline: from 3 to 10 working days depending on complexity (number of fields, nesting, number of post types). Pricing is individual. Ready to solve your task? Contact us for an estimate.
Why choose us
Over 5 years in web development. Completed more than 50 WordPress projects with ACF. We guarantee stable field operation and timely bug fixes after delivery. We keep the code clean—no unnecessary plugins. Ready to organize your admin panel? Contact us—we'll find the optimal ACF structure for your project. Get a consultation via the form on the website or messenger.







