WordPress custom fields for services and projects

A laptop with a neat project folder, a notebook, samples and an orange object on the desk.
Rate this post

WordPress’s custom fields allow you to separate the data for service and project pages from the page layout. You can manage the sector, materials, documents and related services without having to rebuild each page.

For a company website, I’d recommend starting with the content structure, choosing only afterwards between native functions, Advanced Custom Fields and custom code. The first step is to distinguish between the information you can present freely and the information that must maintain a consistent format.

Organise services and projects before adding fields

Separating content, classifications and data

According to the WordPress Codex, custom fields contain additional information known as metadata (meta-donnée in French). Each value is associated with an element via a key, for example customer_sector.

The title identifies the record, whilst the main content describes the work. The fields contain specific information; taxonomies group elements together, for example projects by sector using custom taxonomies.

When creating a company website, I identify three requirements: writing a description, storing data and organising archives. The choice of custom post type in WordPress It, on the other hand, concerns the creation of separate sections, such as “Projects”.

Defining a reusable pattern

To design consistent fact sheets, I start by considering the information the reader needs and who will be responsible for updating them.

This structure distinguishes between the data for the two types of form.

FactsheetInformationSuitable tool
ServiceDescription and benefitsMain content
ServiceInformation sheetFile field
ProjectYear of completionNumeric field
ProjectClient sectorTaxonomy
ProjectRelated servicesReport field

A shared classification system, such as the sector, often works better as a taxonomy than as free-form text.

A wooden desk with an open laptop, photos of architectural projects and coloured folders.

WordPress custom fields: native, ACF or code

When native functions are enough

WordPress already has a metadata system. update_post_meta() saves a value associated with a piece of content, whilst get_post_meta() It retrieves it. You therefore do not need a plugin to store additional data.

A native interface is essential. For those updating websites for SMEs, drop-down menus, instructions and value checks help to minimise errors.

I opt for custom code when specific rules or integrations are required, often with the support of developers. As a rule, a custom plugin handles data collection, whilst the theme manages its presentation.

What do ACF and ACF PRO offer?

Advanced Custom Fields provides an interface for managing structured data, as explained in the Guide to ACF fields. Advanced custom fields are useful when a form requires complex data, such as lists of repeatable items or content organised into multiple sections. The plugin includes over 30 field types and has benefited from more than ten years of contributions from the community.

According to SearchWP, ACF is installed on over a million websites. It also allows you to register post types and taxonomies via the interface, without writing any code.

ACF PRO adds the repeater field, gallery, clone, flexible content, options page and ACF blocks for Gutenberg. The free version may be sufficient for simple forms; I opt for PRO when these features meet a specific need.

If you’re already using Meta Box, consider its capabilities before introducing a second system.

Configuring ACF for company profiles

When organising services and projects, I follow a sequence that separates configuration, compilation and rendering.

  1. Specify the content in question: an existing page or a post type of “Services” or “Projects”.
  2. Create a group of fields in ACF, with clear labels and consistent technical names.
  3. Set the position rules to display the group only on the relevant tabs.
  4. Fill in the form in full and link the values to the public template.

ACF allows you to associate fields with posts, pages, users, taxonomy terms, media and comments. The options pages require the relevant PRO feature.

For users, you can manage a professional qualification; for terms, a category image; and for media, additional information about the asset. However, each piece of data must have a specific purpose.

For technical terms, I prefer keywords such as project_year e service_document. Changing them after compilation may leave values associated with the old keys.

A repeat field is useful for a sequence of items, such as the stages of a project. To link services that have already been published, however, a relationship field avoids having to retype their titles and descriptions.

Display the data and make it searchable

Link the values to the form template

Saving a field does not mean displaying it on the page. In the PHP template, get_post_meta(get_the_ID(), 'project_year', true) retrieves the value; esc_html() This makes it suitable for output as text.

With ACF, you can use get_field(), which applies the formatting specified for that field type. The template must, however, handle empty values and use the appropriate escape sequence: esc_url() for a link, for example.

A field saved in the database does not automatically appear on the form and does not automatically become structured data for Google.

Even with Elementor, dynamic linking depends on the features available in the project settings.

Distinguishing between internal search, filters and SEO

SearchWP takes custom fields into account alongside the title and content. In the search engine configuration, you can include selected custom fields and assign them a weighting.

For ACF repeaters, SearchWP groups the sub-fields together as a single engine attribute. I would index data that is useful for searching, whilst excluding internal notes and confidential information.

Filters are another feature: the documentation on the FacetWP integration with ACF describes how fields are used as the source for facets.

When it comes to technical SEO for WordPress, what the template publishes also matters. Internal search does not guarantee a better ranking for the website.

WooCommerce: distinguishing between products, checkout and orders

A product field, such as «Material» in a plain text field, describes the item; a checkout field collects information for the purchase. Order data, on the other hand, requires separate management.

Before adding any code, I’ll take a look at the information already provided in the catalogue. The ACF guide to product ranges explains the plugin-based alternative.

In the historical tutorials, woocommerce_product_options_grouping creates the field, whilst woocommerce_process_product_meta preserves its value. In the following example, I use woocommerce_product_options_general_product_data to insert it into the classic editor.

PHP 5.6.25, PHP 7 (recommended), MySQL 5.6.33, WordPress 4.7 and WooCommerce 3.9 are requirements for an outdated tutorial, not guidelines for new installations.

A small ceramic vase, an open parcel box and a tablet on a wooden table.

Complete example for a simple product field

This plugin adds “Material” to simple products. Use is_admin() to separate the administrative hooks from the public ones. The constant ensures that the field name remains unique, in line with the ‘Don’t repeat yourself’ principle.

<?php
/**
 * Plugin Name: AF Materiale prodotto
 */


defined('ABSPATH') || exit;


final class AF_Materiale {
    private const KEY = '_af_materiale';


    public function __construct() {
        if (is_admin()) {
            add_action(
                'woocommerce_product_options_general_product_data',
                [$this, 'campo']
            );
            add_action(
                'woocommerce_process_product_meta',
                [$this, 'salva']
            );
        } else {
            add_action(
                'woocommerce_product_thumbnails',
                [$this, 'mostra']
            );
        }
    }


    public function campo() {
        woocommerce_wp_text_input([
            'id' => self::KEY,
            'label' => 'Materiale',
            'wrapper_class' => 'show_if_simple',
        ]);
    }


    public function salva($id) {
        $nonce = $_POST['woocommerce_meta_nonce'] ?? '';
        $valore = $_POST[self::KEY] ?? null;


        if (!is_string($nonce) || !is_string($valore)) {
            return;
        }


        if (!wp_verify_nonce(
            sanitize_text_field(wp_unslash($nonce)),
            'woocommerce_save_data'
        ) || !current_user_can('edit_post', $id)) {
            return;
        }


        $prodotto = wc_get_product($id);


        if (!$prodotto || !$prodotto->is_type('simple')) {
            return;
        }


        update_post_meta(
            $id,
            self::KEY,
            sanitize_text_field(wp_unslash($valore))
        );
    }


    public function mostra() {
        global $product;


        if (!$product || !$product->is_type('simple')) {
            return;
        }


        $valore = get_post_meta(
            $product->get_id(),
            self::KEY,
            true
        );


        if ($valore !== '') {
            echo '<p>' . esc_html('Materiale: ' . $valore) . '</p>';
        }
    }
}


new AF_Materiale();

The code requires WooCommerce to be active and the classic template to be running woocommerce_product_thumbnails. A fully block-based model requires a different approach to integration.

This example relates to products, not HPOS orders: for order metadata, I use the WooCommerce CRUD APIs, with wc_get_order(), update_meta_data() e save().

Safety, maintenance and costs of the building

Protecting data and business continuity

Before making any changes to the structure, I recommend carrying out a full backup and testing on the staging environment. The nonce verifies the origin of the request; the authorisation check determines whether the user is permitted to modify the content.

wp_unslash() removes the slashes added to the received data; sanitize_text_field() cleans up the text. None of these functions replaces the specific checks required for emails, numbers or URLs.

When redesigning the website, I document keys, types, dependencies and destinations. To transfer data, there are procedures for Exporting ACF fields, including using specialised tools.

Assess the complexity and the work required

When carrying out WordPress maintenance, I also take into account templates, queries and integrations. When optimising site speed, it is the code executed and the data loaded that matter, not just the number of plugins.

A responsive website must also handle long fields, documents and repeatable elements without compromising the user experience on smartphones.

Costs and timelines depend on objectives, content, the number of pages, functionality, integrations and the initial conditions. Migrating an existing archive involves different tasks to setting up a few new forms.

To implement this structure when building professional websites, Find out about WordPress website development.

Frequently Asked Questions

Is ACF PRO required for service sheets?

No. For text, numbers, files and reports, the free version of ACF is sufficient. I’d recommend the PRO version if you need repeaters, galleries or other exclusive features.

Do custom fields automatically improve SEO?

No. They organise the data, but published content, page structure and technical configuration remain separate tasks.

A clear structure makes the files easy to manage

For services and projects, I recommend defining the following first Data and editorial responsibility. Then I choose the tool and plan how to display each piece of information, without duplicating existing functions.

As a freelance WordPress developer based in Ciampino, in the Rome area, I also work online with companies throughout Italy. If you need to organise or redesign your product pages, Let’s talk about your website project.

Categories

Latest articles

WordPress white screen
WordPress white screen: how to regain access
A laptop displays a loading icon next to an external hard drive.
Error 413 in WordPress: how to resolve upload issues
A laptop with index cards arranged on the desk next to an orange notebook.
Custom post types in WordPress: when to use them in a business
A laptop on a desk is showing a loading screen.
WordPress: fixing the ‘too many redirects’ error
Powered by Joinchat