Skip to content

t1k:marketing:monetization:cloudx-price-floor

FieldValue
Modulemonetization
Version1.16.9
Efforthigh
Tools—
/t1k:marketing:monetization:cloudx-price-floor

Manage CloudX First Look bidfloors (price floors) for any app, in either direction (raise or lower/revert), through an editable floors.json.

⚠️ Money-risk. Bidfloors move live ad revenue. This skill NEVER publishes without: (1) a read-only account check, (2) a before→after preview, (3) a published smoke of one item, (4) explicit user confirmation before the rest. Low-volume segments (P90 off <100 imp) are flagged, never silently set. See rules/ad-network-mcp-write-safety.md.

Activate for changing/setting/reverting CloudX price floors, computing First Look P90 floors from MAX data, or applying a hand-edited floors.json.

  • CloudX MCP connected (tools mcp__cloudx__GetConfigShow, GetConfigValidate, PostConfigEdit, PostConfigPublish). If not connected, run mcp__cloudx__authenticate and have the user complete login. This skill hard-depends on the CloudX MCP server for all live reads/writes.
  • MAX report key MAX_REPORT_KEY — needed only for Compute mode. Provide it via process.env.MAX_REPORT_KEY, --env <file>, or a MAX_ENV_FILE pointing at a .env. Never commit the key. It is a prerequisite, not a shipped secret.
  • Node available (node). Scripts are .cjs under scripts/.
COMPUTE ─▶ floors.json ─▶ (optional hand-edit) ─▶ APPLY ─▶ live

floors.json is the source of truth. To change a floor up or down, edit its bidfloor and re-apply. To revert, apply a saved older floors.json (every run is timestamped; every published CloudX version is in config/history).

Generated artifacts (floors.json, edit bodies, plans) are written to a cross-platform work dir: --out/--out-dir flag → CLOUDX_WORK_DIR env → os.tmpdir()/cloudx-floors. No hardcoded absolute paths.


  1. User gave explicit floor numbers / a floors.json to apply → skip Compute, go to APPLY.
  2. User wants floors derived from performance (“p90”, “from MAX data”, “last N days”) → COMPUTE first, then APPLY.
  3. User wants to revert → find the prior floors.json (or the target config/history version) → APPLY that.

COMPUTE (Mode A) — derive floors from MAX data

Section titled “COMPUTE (Mode A) — derive floors from MAX data”
  1. Resolve the app: call GetConfigShow (read-only), find the app by name/bundleId/appKey, note its id. (Save the big result — it auto-writes to a tool-results/*.txt; parse with a tiny Node script, don’t Read whole.)
  2. Run:
    node scripts/compute-floors.cjs --pkg <bundleId> --platform android \
    --start <YYYY-MM-DD> --end <YYYY-MM-DD> \
    --geos US,RU,BR,WWnoUS (or: --top-geos 3) \
    --formats Interstitial,Rewarded --uplifts 10,30,40 \
    --priority 10:5,30:3,40:1 --out floors.json
    Window guidance (First Look guide, Mediation branch): ~7–15 days. Shorter windows (e.g. 3 days) make low-volume segments volatile — surface this.
  3. Read the preview. Flag every VERY-LOW / LOW-VOL segment to the user and ask how to handle them (apply / skip / longer window) before applying.
  1. Auth + account check (read-only): GetConfigShow → confirm account_id is the intended publisher account and permission includes configuration:write.
  2. Build ops:
    node scripts/build-ops.cjs --floors floors.json \
    --config <path-to-GetConfigShow-result.txt> \
    --bidders meta,mintegral,unityAds,vungle --out-dir .
    It resolves the app + ad units, decides create vs update per line item, and writes edit_smoke.json, edit_rest.json, edit_full.json + a before→after table. If it errors on an ambiguous ad unit (e.g. a rewarded placement whose type is mislabeled), set adUnits.<Format> to an explicit id in floors.json.
  3. Present the before→after table to the user (name, old→new, priority, op, flags).
  4. SMOKE: PostConfigEdit with edit_smoke.json → parse validation (must be valid:true, error_count:0; the ~325+ account-wide warnings are pre-existing noise — filter issues to your own item names) → PostConfigPublish with the returned draft id → GetConfigShow and confirm the one item is live with the right bidfloor (stored in micros: $14.60 → 14600000).
  5. CONFIRM with the user, then apply the rest: PostConfigEdit with edit_rest.json → validate → PostConfigPublish → verify count.
  6. Report every changed line item id + old→new floor + the new live version_number.
  • Keep each run’s floors.json (name it with the window, e.g. floors_<app>_<window>.json). To roll back, run APPLY with the older file — build-ops emits updates back to those floors.
  • Or target a prior published config: GetConfigHistory → pick the version → read its floors → APPLY. Never delete-then-recreate to revert; update in place.
  • Read-only account/permission check before any write.
  • Before→after preview + smoke + explicit confirm before the full publish.
  • Low-volume (P90 off <100 imp) is flagged VERY-LOW; never apply silently — ask. (Guide: “don’t floor tiny volume; don’t extrapolate.”)
  • Never print MAX_REPORT_KEY or any API key.
  • One batch at a time; re-read state before any retry (a timeout may have partially applied).

Verified against a live config — see references/cloudx-api.md:

  • bidfloor INPUT = decimal USD CPM (14.6); STORED = micros (14600000).
  • target include = {"countries":["USA"]}; exclude = {"exclude":{"countries":["USA"]}}.
  • Country codes: 3-letter ISO stored (USA/RUS/BRA); MAX returns 2-letter — the core maps them.
  • Config JSON data is camelCase (bundleId, appId, uppercase type); ad unit appId has no @.
  • create_line_item auto-generates ids; update_line_item patches by id (omitted fields unchanged); delete_line_item by id.
  • Existing floors in a different naming convention: build-ops matches create-vs-update by the skill’s Geo_Format_val_UP%_date names. If the app already has floors named differently (e.g. Format_Geo order, Rw, lowest tiers), they won’t match → applying creates would DUPLICATE floors. build-ops warns and writes orphans.json (delete candidates). Decide with the user: delete the orphans first (combine delete_line_item + create_line_item in one edit) or rename-match.

All-apps mode + naming convention (studio standard)

Section titled “All-apps mode + naming convention (studio standard)”

The studio’s de-facto convention is Format_Geo: Inter_US_<val>_<tier>_<date>, Rw_RU_...; tiers lowest / 30% / 40% (iOS lowest / 40% / 50%), where lowest = P90 base (~0% uplift), priorities P5 / P3 / P1. This is the skill’s default (--naming format_geo). Rw (not Reward) is the rewarded token. The alternate --naming geo_format (US_Inter_..._10%_...) exists but is the minority; using it on studio apps forces delete-recreate.

All-apps dry-run + classification (create / update / delete-recreate / skip):

node scripts/plan-all.cjs --config <GetConfigShow.json> --start <d> --end <d> \
[--naming format_geo] [--top 3] [--min-imp 100]

Writes plan_<naming>.json (per-app ops, ids) — READ-ONLY, no CloudX writes. Rollout from a plan: per-app, smoke + confirm each (never mass-blast ~hundreds of live line-item ops). Guards: never delete-recreate to an empty set (strip protection); skip apps with no MAX data / no inter-reward ad unit.

  • scripts/floors-core.cjs — geo→target, ISO map, segment P90, env; re-exports MAX fetch + weighted P90 from .claude/scripts/t1k-marketing-max-p90-core.cjs (shared SSOT)
    • work-dir resolution (SSOT).
  • scripts/compute-floors.cjs — Mode A CLI.
  • scripts/build-ops.cjs — Mode B op builder (create/update resolution).
  • scripts/plan-all.cjs — all-apps dry-run planner.
  • references/cloudx-api.md — MCP tools + verified field shapes + flow.
  • references/parameters.md — every CLI flag, JSON schema, and code-level knob.
  • examples/floors.example.json — annotated JSON template.
  • rules/ad-network-mcp-write-safety.md — money-risk write gate (this skill obeys it).
  • rules/preview-first-batch.md — smoke before scaling.
  • Skill t1k-marketing-monetization-cloudx — CloudX mediation reporting (revenue pull); this skill is the provisioning/price-floor counterpart.
  • Skill t1k-marketing-analytics-crawldata — the MAX / First-Look data pipeline this builds on.