---
title: ACF fields in the Content Cloud output
slug: editorial/acf-fields-in-the-content-cloud-output
docTags: 
createdAt: 2026-10-12T06:01:00.192Z
---

How ACF fields appear as Content Cloud properties. Written for integrators who consume a headless Hub's output and need to know what shapes to expect before they write a schema against it.

The document has two parts:

- **Part 1 — How it works** is reference material. Everything there is intended behaviour; it is listed because it regularly surprises people on first contact.
- **Part 2 — Known issues** is the short list of things that are genuinely inconsistent and that you have to work around on the consumer side.

***

# Part 1 — How it works

## A field becomes one or two properties

A field with a simple value becomes one property carrying that value.

A field with a structured value — a post object, an image, a repeater, a gallery — appears twice:

1. **flattened**, one property per leaf, with the path in the key: `parent_page.ID`, `parent_page.post_title`, `parent_page.thumbnail`
2. **as one JSON property** under the bare field name, with property type `JSON`: `parent_page` → `{"ID":"…","post_excerpt":"","post_title":"…","thumbnail":""}`

Switching on **"Publish only as JSON"** in the field settings leaves only the JSON property. New fields have this setting enabled by default; older fields generally do not, which is why most existing projects see both forms.

Alongside the flattened form you also get `_element_count` properties — `gallery._element_count`, `repeater_field.0._element_count` — carrying the number of entries. They are not part of the JSON document; ignore them if you read the JSON property.

## An empty field is normally absent

An empty field is normally not published at all, so a property key can be present on one article and missing on the next. The field setting **"Always submit"** keeps an empty field in the payload.

If you need a property to always be present so you can validate a single schema, ask the editorial team to enable "Always submit" on that field. Otherwise treat a missing key as empty.

Menu items are the exception: their fields are always published without empty values, so "Always submit" makes no difference there and a missing key always means empty.

## References are Purple content ids, not WordPress ids

`parent_page.ID` is a UUID such as `af45b7d4-5951-4850-837d-a591d15fbb7e`, not the WordPress post id. A reference points at the id the referenced article has in the Content Cloud, so it can be followed in the published output. Taxonomy fields do the same in their `id`.

## Conditionally hidden fields are absent

A field with conditional logic is absent from the output whenever its condition is not met — not empty, absent.

This applies per repeater row, so two rows of the same repeater can carry different sets of sub-fields. Do not assume every row has the same keys. (Blocks behave differently — see issue 4.)

## Repeater rows are re-indexed

Row indices in the JSON array are always consecutive, even when rows were deleted in between. A row's position is therefore not a stable identifier across publishes.

## Image dimensions describe the delivered image

`width` and `height` on a published image describe the file its `url` points at, which is the cropped version, not the original upload. Use them for layout; they match the URL. Images without dimension information keep the values ACF reports.

## Date fields have their own property type

A Date Picker or Date Time Picker field whose return format is `TIMESTAMP` gets property type `TIMESTAMP` and a value like `2025-02-20T18:00:00Z`. Any other return format gives a plain string formatted exactly as configured, e.g. `02/20/2025 (18:00:00)`.

If you need a machine-readable date, set the field's return format to `TIMESTAMP`.

***

# Part 2 — Known issues

## 1. An empty field changes its property type

A Post Object field arrives as property type `JSON` while it holds a value, and as property type `STRING` with the value `""` while it is empty. The type of one and the same property key is therefore not stable over time.

This affects every field type that appears as JSON, not only Post Object: repeater, flexible content, relationship, gallery, image (return format *array*), file, link, taxonomy, user, Curator Collection, Google Map, icon picker, multi-select and checkbox.

It only shows on fields with **"Always submit"** enabled. Without that setting an empty field is not published at all, so the type never flips — the property is simply absent.

It also only shows on fields shown **on an article or on an image**. A field on a block is part of that block's `dataJSON` and stays JSON whether or not it has a value; a field on an options page or a term is not published as an article property at all.

**Workaround.** Check the property type, or treat `""` as "no value" alongside the parsed object.

:::BlockQuote
**Status:** this is being addressed. In an upcoming release an empty field will carry the empty JSON document its definition implies — `{}` for object-shaped fields, `[]` for list-shaped ones — and keep property type `JSON` in both states. The value changes from `""` to `{}`/`[]`, so a consumer that branches on truthiness (`if (props.parent_page)`) will start treating an empty field as filled: `""` is falsy, `{}` is not. Prefer an explicit emptiness check.
:::

## 2. Empty values inside a group or repeater appear as an empty string

Inside a JSON document, a sub-field that would normally hold an object holds `""`:

```json
{ "sub_ref": "", "sub_txt": "Some text" }
```

rather than `{"sub_ref": {}, …}` or `{"sub_ref": null, …}`.

This is issue 1 one level down: the *property* type stays `JSON`, but the shape inside the document varies with the content. Unlike issue 1, it is not scheduled to change.

**Workaround.** When reading a nested structured value, accept both the object and `""`.

## 3. File and Link fields ignore their return format

A File field set to return *File URL* or *File ID* still gives an object:

```json
{ "name": "document.pdf", "url": "https://…/document.pdf", "purpleId": "…" }
```

A Link field set to return *Link URL* likewise still gives the full object:

```json
{ "target": "_blank", "title": "Example", "url": "https://example.com" }
```

**Workaround.** Read `url` from the object, and disregard the return-format setting for these two field types.

The **Image** field is not affected: *Image URL* and *Image ID* do give a plain value, and only *Image Array* gives an object.

## 4. Blocks publish conditionally hidden fields

An ACF field on a block appears in the block's `dataJSON` even when its conditional logic says it should be hidden — the opposite of how the same field behaves on an article.

**Workaround.** For block fields, evaluate the controlling field yourself rather than treating the presence of a key as "the editor filled this in".

## 5. References to deleted content appear as empty objects

A Taxonomy field entry whose term no longer exists is published with empty strings throughout, instead of being dropped:

```json
{ "id": "", "name": "", "slug": "" }
```

**Workaround.** Treat an empty `id` as a dangling reference and skip the entry rather than rendering it.

A **Curator Collection** reference behaves similarly, but by design: a deleted collection keeps its `id`, with an empty `name`, so the reference is not silently lost before an editor can replace it. Check `name` there rather than `id`.
