Skip to content
Back to skills

Wp Woocommerce

ASecurity

WooCommerce store practice for sites this plugin builds — the catalog, store and full tiers recorded as store.tier in .wp-create.json and the plugins each installs (and the ones deliberately avoided, with reasons), store-kit's catalog mode and Stripe keys kept as constants in wp-config.php, Stripe test mode, the HPOS, block-checkout and card-testing defaults a WP-CLI install gets wrong, and the woo-setup.php script /wp-woo-setup runs to bring a store in line with the store block. Use when cre...

  • 6 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added October 5, 2026
developmentgophpbashtestinggitapidatabase

Works with

  • cli
  • api

Security analysis

A100/100

Pro scans all 4 files and shows the line behind each finding

Scanned October 7, 2026

npx -y skills add yojahny55/claude-wp-builder --skill wp-woocommerce --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Wp Woocommerce?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Wp Woocommerce
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/yojahny55-wp-woocommerce/badge)](https://www.skillsdirectory.com/skills/yojahny55-wp-woocommerce)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: wp-woocommerce
description: WooCommerce store practice for sites this plugin builds — the catalog, store and full tiers recorded as store.tier in .wp-create.json and the plugins each installs (and the ones deliberately avoided, with reasons), store-kit's catalog mode and Stripe keys kept as constants in wp-config.php, Stripe test mode, the HPOS, block-checkout and card-testing defaults a WP-CLI install gets wrong, and the woo-setup.php script /wp-woo-setup runs to bring a store in line with the store block. Use when creating, configuring or auditing a WooCommerce store, choosing a store tier or a store plugin, turning on catalog mode, or asking why Stripe keys live in wp-config.php. Not for translating products (wp-polylang), or a product post type for a client who will never sell online (/wp-cpt).
user-invocable: false
---

# WooCommerce stores

A store is a recorded decision, like the i18n strategy and the demo mode. The `store` block in
`.wp-create.json` says what the store sells and how, `/wp-woo-setup` brings WooCommerce in line
with it, and every other command reads the block instead of guessing. This skill is the
knowledge behind those values. It acts on nothing: the command runs the scripts.

Read the block, never infer it: `store.tier` is the tier, `store.enquiry` the catalog's enquiry
channels, `store.checkout` (with `store.checkout_reason`) the checkout type, and
`store.payments.mode` the payment mode.

## The three tiers

| `store.tier` | What it is | Profile |
|---|---|---|
| `catalog` | Products and prices, nothing purchasable. Runs on WooCommerce with buying switched off by `store-kit`, so moving up a tier keeps every product, with no migration. `store.enquiry` records which enquiry channels apply — `form`, `where-to-buy`, `whatsapp` — and only `where-to-buy` works out of the box, as WooCommerce's External product type: no starter theme renders the enquiry form or the WhatsApp button. | `${CLAUDE_PLUGIN_ROOT}/templates/profiles/woo-catalog.json` |
| `store` | Cart, block checkout, Stripe in test mode, shipping, tax, SMTP, Turnstile, and cookie consent where the market needs it. | `${CLAUDE_PLUGIN_ROOT}/templates/profiles/woo-store.json` |
| `full` | `store` plus abandoned-cart email, email marketing, reviews, search and filters, swatches, wishlist, and Google and Meta feeds. | `${CLAUDE_PLUGIN_ROOT}/templates/profiles/woo-full.json` |

`references/plugins.md` holds why each plugin is there, why the popular alternatives are not,
and the add-ons (digital downloads, print-on-demand, wholesale, multilingual). Read it before
adding, removing or swapping a plugin in a store profile: `tests/checks/wp-profiles.sh` fails
a profile plugin with no row under Picks, or one listed under Avoid.

When a client will never sell online, a product custom post type from `/wp-cpt` is lighter
than any tier: no sessions, no Action Scheduler, no Store API. The catalog tier is for the
client who may sell later.

## What a WP-CLI install gets wrong

Measured on WooCommerce 11.1.2 unless marked (source).

- **New-store defaults never run.** They are hooked to `admin_init` (source), so HPOS, "coming
  soon" and the onboarding defaults wait for the first wp-admin visit. Setup sets every value
  itself.
- **HPOS must be on before the first order.** On a store with no orders `wp wc hpos enable`
  creates the tables and switches; after an order exists WooCommerce will not switch on its own.
- **Pages.** Activation creates Shop, Cart, Checkout (block markup) and My account, and a draft
  Refund policy — no Terms page.
- **Polylang gives WooCommerce's pages no language** when it was configured after they were
  created, and `product` is not a translated post type by default. Setup assigns the default
  language to the store pages. Products stay untranslated: this plugin has
  no bridge between WooCommerce and Polylang.
- **Card testing.** Both Store API limiters are off by default, and card-testing scripts post to
  `/wc/store/v1/checkout` directly even on a classic-checkout store. Setup turns on the
  **checkout limit** (`woocommerce_feature_rate_limit_checkout_enabled`): 3 attempts a minute
  per IP, refused as HTTP 400 `rate_limit_exceeded`. It never turns on the **general limiter**
  (`woocommerce_store_api_rate_limit_options`) — both keep one per-IP row, so ordinary cart
  traffic dilutes the checkout limit to the general one.
- **Turnstile loads its WooCommerce integration only once `cfturnstile_tested` is `yes`** (source),
  normally set by testing the keys in wp-admin. Setup sets it together with Cloudflare's
  always-pass test keys on a local site; real keys are a launch step.
- **Background jobs.** With `DISABLE_WP_CRON`, Action Scheduler runs only on wp-admin requests
  (source); setup runs the queue once and reports the missing cron (PERF-061, PERF-062).
- **Emails.** Every send attempt leaves an order note (`Email "New order" sent.`), which is how a
  test proves email without an inbox.

## Practices every store gets

- **API keys never at rest; a rotated webhook secret is the one exception.** Stripe's API keys
  are `STORE_KIT_STRIPE_*` constants in `wp-config.php`; `store-kit` supplies them when the
  gateway reads its settings and strips them when it saves, so a database dump or clone carries
  none of those, and SEC-040 (which reads the raw row) agrees. A webhook-secret constant only
  ever seeds an *empty* field, because Stripe rotates that secret on its own when Stripe
  reconfigures webhooks (connect, re-key, the settings button, or after a plugin update) — a
  rotated value is left to reach the database, with an admin notice naming the now-stale
  constant. Configure Stripe with API keys, not "Connect with Stripe", which saves keys to the
  database.
- **Paid downloads stay closed.** Download method `force`; the native nginx and Caddy templates
  deny `woocommerce_uploads`, because nginx never reads WooCommerce's `.htaccess` (SEC-039).
- **Guest checkout on, account creation offered after purchase, coupons on.** A forced account is
  among the top reasons US shoppers abandon a checkout (Baymard, 2025).
- **Block checkout by default.** It is WooCommerce's default and where new features land; classic
  PHP checkout hooks do not fire on it. `store.checkout: shortcode` only with a written reason in
  `store.checkout_reason` — an extension that does not support blocks.
- **Test mode, always.** `store.payments.mode` is `test`, and the validator accepts nothing
  else. Cash on delivery only in a `local` environment, for the automated test order; "coming
  soon" everywhere else.
- **No command takes a store live.** Live Stripe keys, test mode and "coming soon" off, cash on
  delivery off and real Turnstile keys are one launch step with a fixed order, and it is not
  built: setup refuses a live key. Do not change these by hand — stop and hand the launch to
  the operator.
- **Abandoned-cart email depends on the market.** The US is opt-out (CAN-SPAM); the UK allows a
  soft opt-in only for an address typed at checkout; in the EU — Germany above all — treat it as
  advertising that needs prior consent.

## The scripts

Never run them directly: `/wp-woo-setup` runs `scripts/woo-setup.php` (dry run in its Step 5,
apply in Step 6) after the gates they depend on. What the command passes, for reading its
output:

```bash
$WP eval-file "${CLAUDE_PLUGIN_ROOT}/skills/wp-woocommerce/scripts/woo-setup.php" '<project-path>' [dry-run] [force]
```

- **Arguments** are bare words, because `wp eval-file` refuses a `--flag` it does not know.
- **Exit `0`**: the store matches the block, `degraded` lines allowed. **Exit `1`**: refused
  before anything is written, with a `refused:` line saying why.
- **It needs** native WP-CLI on the host (`environment.engine` is `native`), with WooCommerce
  and `store-kit` active; otherwise it refuses.
- **Report-only:** on a store that has orders, or was adopted, and where setup has never run, it
  writes nothing and reports what it would change — until the operator passes `force`.

Setup records a hash of every value it writes in `store_kit_setup_state`; a value that no
longer matches that hash is the client's and is left alone unless `force` is passed. The one
exception is launch state — "coming soon", Stripe's `enabled`/`testmode`, cash on delivery —
which a store with orders never has written for it, absent or not, force or not: change it in
WooCommerce instead.

`scripts/woo-lib.php` holds setup's decisions with no WordPress calls, so
`tests/checks/woo-lib.sh` runs them under bare PHP. Read it to see how a value is compared or
decided; it is never run on its own. Both files hold the PHP 7.4 floor.

Files in this skill

  • SKILL.md6 KB
  • references/plugins.md6.1 KB
  • scripts/woo-lib.php8 KB
  • scripts/woo-setup.php36.7 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.