Skip to content

settings_data.json: Storage & Presets

TL;DR: How merchant setting values are actually stored, the current/presets/platform_customizations structure, hard limits, and what switching a preset really changes.

config/settings_data.json stores the values for whatever settings_schema.json declares. It’s the file the theme editor actually writes to every time a merchant changes something. Facts on this page are verified directly against shopify.dev’s settings_data.json reference.

ObjectRequiredDescription
currentYesEvery setting value currently active in the theme editor
presetsYesOne object per theme preset, in the same shape as current
platform_customizationsNoAdded automatically by Shopify if a merchant uses a platform-controlled setting — you never write this yourself
{
"current": {
"color_page_bg": "#FFFFFF"
},
"presets": {
"Default": {
"color_page_bg": "#000000"
}
}
}

Any time a merchant changes a setting in the theme editor, current updates immediately to reflect it.

These aren’t stylistic recommendations — they’re enforced platform limits:

  • A theme can’t contain more than five presets total.
  • settings_data.json can’t exceed 1.5MB.

Plan your preset strategy (see Theme Presets) with the five-preset ceiling in mind from the start, rather than discovering it after building a sixth.

What switching a preset actually changes: presentational settings only

Section titled “What switching a preset actually changes: presentational settings only”

This is the single most commonly misunderstood part of the whole preset system. Selecting a different theme preset doesn’t overwrite every setting value — only “presentational” ones.

Presentational settings are the input types tied to a visual style, not to content:

checkbox, color, color_background, color_palette, color_scheme,
color_scheme_group, font_picker, number, radio, range, select
// ✅ Switches when a merchant picks a different preset — these are
// presentational: colors, fonts, numeric/toggle style choices
{ "type": "color", "id": "color_primary" }
{ "type": "font_picker", "id": "type_heading_font" }
{ "type": "range", "id": "border_radius" }
// ❌ Does NOT switch when a merchant picks a different preset —
// these hold content, not style, and a preset switch leaves them alone
{ "type": "text", "id": "announcement_message" }
{ "type": "image_picker", "id": "hero_image" }
{ "type": "url", "id": "cta_link" }

If you’re building a theme preset expecting it to also swap out a merchant’s hero image or announcement text, it won’t — only the presentational-type settings listed above are affected. A preset genuinely changing content, not just style, requires editing that preset’s "sections" data directly (see Theme Presets), not relying on the automatic preset-switch behavior.

Shopify exposes a custom CSS setting directly in the theme editor, at both the theme and section level. You can’t add, hide, or remove this setting from your schema — it’s built into the platform. Any custom CSS a merchant adds through it is stored in the platform_customizations object’s custom_css attribute (or, for section-level custom CSS, in that section’s own JSON template data).

As a theme developer, never add this setting yourself, and never edit its value once a merchant has set one. If you want to offer CSS customization, do it through your own theme settings feeding into a {% stylesheet %} tag (see CSS in Shopify), not by touching this platform-owned mechanism.

settings_data.json holds real merchant data once installed

Section titled “settings_data.json holds real merchant data once installed”
Section titled “How they connect: the setting id links them together”

A setting’s id in settings_schema.json is the same key settings_data.json, and every {{ settings.x }} reference in Liquid, uses to read or write its value. Treat a shipped id as permanent, the same way you’d treat a product SKU once it’s in customers’ order history:

// settings_schema.json defines the setting exists, with this id:
{ "type": "color", "id": "color_primary", "label": "...", "default": "#1a5f4f" }
// settings_data.json stores a value under that exact id:
{ "color_primary": "#1a5f4f" }
{# Liquid reads it by the same id: #}
{{ settings.color_primary }}
// ❌ WRONG — renaming the id breaks the link. Every merchant who
// already customized "color_primary" now has an orphaned value in
// their settings_data.json, and the newly-named setting falls back
// to its schema default, silently discarding their customization
{ "type": "color", "id": "brand_color_primary", "label": "...", "default": "#1a5f4f" }

If a setting truly needs renaming, treat it as a major-version change (see After Approval) with a real migration path, not a silent rename.

A changed schema default doesn’t reach existing merchants

Section titled “A changed schema default doesn’t reach existing merchants”
// You change this default from #1a5f4f to #2b2b52 in settings_schema.json...
{ "type": "color", "id": "color_primary", "default": "#2b2b52" }

A merchant who installed the theme last month, and never touched the color setting, is still on #1a5f4f. That value was already written into their store’s settings_data.json the moment they installed the theme. Changing a schema default only affects merchants who install the theme after the change. If every existing merchant needs to see a new default, a schema change alone won’t do it — that requires a separate migration step.

✅ Do❌ Don’t
Plan presets with the hard 5-preset ceiling and 1.5MB file-size limit in mind, not as an afterthought.Building more than five theme presets and discovering the platform limit only when a submission fails.
Remember that switching a preset only changes presentational-type settings. Design your presets around that limitation, not around an assumption that everything switches.Assuming a theme preset swaps out content settings (text, images, links) the same way it swaps colors and fonts — it doesn’t.
Never add or edit the platform-controlled custom_css/platform_customizations setting yourself.Manually adding or editing a custom_css setting, which conflicts with the platform-controlled mechanism Shopify already provides.
Treat a setting id as permanent once shipped, and a schema default change as something that only reaches fresh installs.Renaming a setting id without a migration plan, silently discarding merchant customizations.
Assuming a changed schema default reaches already-installed merchants. It only affects fresh installs.
  • Required: current, presets. Optional, Shopify-managed: platform_customizations.
  • Hard limits: 5 presets max, 1.5MB file size max.
  • A preset switch changes only presentational settings (color, color_background, color_palette, color_scheme, color_scheme_group, font_picker, checkbox, number, radio, range, select) — never content settings.
  • Never touch the platform-controlled custom_css/platform_customizations setting yourself.
  • A setting id links schema, data, and Liquid together — treat it as permanent once shipped.