Two kinds of knobs
Every MAM Suite install is full of switches. The trick to keeping them straight is knowing they split into two families — and that those two families behave nothing alike.
App settings describe the mobile app itself. They control what your users see and how the app behaves on their phones: the login screen wording, the global font, whether the home screen shows a tab bar, your colors, which fields appear on a form. There are nearly three hundred of them. The important thing to understand is that app settings are data that travels to the device — they get folded into the JSON payload (the bundle of data the app downloads from your site), so changing one changes the live app, often without anyone rebuilding a thing.
Plugin settings, on the other hand, describe the WordPress side of the install. They control how a plugin does its server-side job — which email address gets a contact-form notification, which Gravity Forms form ID backs a screen, an API key for a third-party service, an entitlement flag. These are ordinary WordPress options and admin-page choices, and they stay on the server. Your phone never sees them directly; at most, it sees the result of them.
Here’s the short version: app settings are about the app, plugin settings are about the plumbing. Hold onto that one distinction and it explains almost everything else — where a given knob lives, who’s allowed to change it, and what happens the moment it does.
Why MAM draws the line here
A MAM app is a thin native shell driven by a JSON payload. The shell itself is generic — it’s the payload that turns one client’s app into a coffee-shop loyalty app and another’s into a real-estate listings app. That architecture forces a clean separation:
- Anything the phone needs in order to render a screen or make a decision belongs in the payload — that’s the app-settings half. It has to be serializable, role-aware, and stable enough that an app built months ago still understands it today.
- Anything only the server needs to do its work has no business in the payload. Shipping a notification email address or an API secret to every single phone would be wasteful at best, and a security leak at worst — that’s the plugin-settings half.
So this isn’t arbitrary housekeeping — it’s the boundary between what the device is allowed to know and what stays behind the server wall. When you’re not sure which kind of setting you’re looking at, ask yourself: would the phone need this to draw a screen or make a decision? If yes, it’s (or should be) an app setting. If it’s only there so WordPress can talk to an email server, a payment processor, or another plugin, it’s a plugin setting.
How app settings are organized
App settings aren’t one flat list. Each one is declared in PHP as a small array with a handful of fields, and it’s those fields that give the whole system its structure. Here’s what a typical declaration looks like:
array(
'category' => 'login',
'title' => 'Login Button Title',
'variable' => 'login_login_button_title',
'type' => 'text',
'id' => 'tsl-setting-login_login_button_title',
'environment' => 'all',
)
A handful of these fields carry the real organizing work:
category groups the setting for the admin UI and the documentation. The categories you’ll run into again and again are the major surfaces of an app — login, home-screen, tabbar, left-menu, listings, forms, general, activity, reviews, misc, plus a few screen- and user-profile-level groupings. (The exact category names are defined in code, and a few have minor variants; the App Settings Reference (app-setting-reference/) is foldered along these same lines, which makes it the easiest way to browse them.) That’s why the settings reference reads like a tour of the app rather than an alphabetical dump.
variable is the key the setting is stored and shipped under — the name the mobile app actually keys on. Once an app has been deployed against a given variable, that name is locked into the contract; renaming it later is a breaking change, not a tidy-up.
type tells the admin UI how to render the input (text, yes-no, color, font, image, and so on), and tells the payload assembler how to serialize the value.
environment is the field that matters most for understanding the boundary — it gets its own section, just below.
Most app settings live in MAM Main’s settings layer (the admin settings page, plus the global/local settings assemblers under includes/app-settings/). Others are contributed by content classes — the objects that represent app screens and actions, things like the login screen, the map, favorites, onboarding, and web/WP-content screens. Any content class can declare its own app_settings(), so the full catalog of app settings is really the union of the central list plus whatever every active content class adds. That’s why the count is “nearly three hundred” instead of a fixed round number — it depends on which content classes and sibling plugins happen to be active.
The environment field: not every app setting reaches the phone
It’s tempting to assume “app setting” means “lands on the device.” Mostly, it does — but the environment field is what actually makes that call. The common values:
all— the ordinary case: the setting is part of the app and gets delivered to whichever audience it applies to.global— the setting applies app-wide rather than per role, and gets injected into the global payload (colors and other site-wide visual settings are the classic example, handled in the global branch of the assembler).backend— used server-side to help assemble the payload, but never emitted as-is to the phone.hidden— declared but never surfaced; for internal use only.
Here’s the practical takeaway: environment is the fine-grained version of that same app-vs-plugin boundary, applied one setting at a time. Even within the app-settings family, the platform reserves the right to keep a value server-side. So “is this an app setting?” and “does the phone actually receive this value?” are related questions, but not the same question — and environment is where they part ways.
This is also why role matters. Some settings vary by user role, while global settings stay the same for everyone. A setting’s scope — global or role-aware — and its delivery — whether it reaches the phone at all — are both decided right here, which is what makes the app-settings layer more than just a glorified options table.
How plugin settings differ in practice
Plugin settings are far more conventional, and you’ll learn to spot them by their habits:
- They’re stored as plain WordPress options, often under a plugin-specific key prefix (a contact-form plugin, for instance, stores its form ID and per-reason notification mappings under keys that begin with its own slug). They’re read with the normal options API, not the app-settings reader.
- They’re configured on plugin admin pages, not in the unified App Setup settings UI — and for things like entitlements and API credentials, there may be no visible UI at all.
- They’re still part of a frozen contract, just a server-side one. Rename a stored option key without a migration and you’ll orphan existing client data just as surely as renaming a
variablebreaks deployed apps. The “don’t rename without a migration” rule applies to both families — only the blast radius differs (server data versus phones already out in the world). - They gate behavior rather than describe appearance. A plugin setting decides whether a feature runs at all, and how it talks to the outside world; the app setting decides how the resulting screen actually looks.
A contact form makes this concrete. The notification email and the backing Gravity Forms form ID are plugin settings, because the server needs them to process a submission. The field labels, placement on the tab bar, and the form’s visual fields live on the app/payload side, because the phone needs them to draw the form. Same feature, two different kinds of knob, split exactly along the “does the phone need it?” line.
Discovering settings without reading the source
Because the app-settings catalog is this large, and assembled from so many places, MAM Main ships a codex / settings-discovery API (mam_codex_manager) whose entire job is to enumerate it. It walks every registered content class and its settings categories, and produces a structured list of every registered setting — category, title, variable, type, environment, plus which content class declared it and any help text that got injected along the way. It’s the tooling-side answer to “what settings exist, and where do they live?” — and it’s what powers settings-search UIs and the auto-generated reference docs, including the per-setting articles in this Codex.
It’s deliberately not user-facing, and not meant for the request-time hot path — enumerating every content class is expensive. Reach for it when you’re building tooling about settings; use the normal per-request setting reader when all you need is one value. The distinction mirrors the bigger theme of this whole article: discovery and documentation are server-side concerns, while the actual setting values are what (selectively) travels to the phone.
How this connects to the rest of the Codex
- The App Settings Reference is foldered by the same
categoryvalues described above — start there once you know roughly which app surface you want to change. - Each plugin’s overview documents that plugin’s own server-side settings (its WordPress options and admin pages) — the plugin-settings half of the picture.
- Content classes are where many app settings actually originate; understanding them explains why two installs can expose different setting catalogs.
- The codex/discovery API is the tooling that ties the whole catalog together, worth a look if you’re building anything that needs to know what settings exist.
Hold onto that one rule and everything else falls into place: if the phone needs it to render or decide, it’s an app setting, and it (usually) ships in the payload; if only the server needs it to do its job, it’s a plugin setting, and it stays behind the wall. The environment field is just that same rule, applied with a finer brush.
Related articles
- Codex and settings discovery (the
mam_codex_managerAPI) - Content classes overview
- Settings cascade overview
- Plugin: mam-contact-form (an example of server-side plugin settings)
