No-write payload and mapping preview
SEO_BLOG_PUBLISH_TOKEN='<tenant-token>' \
SEO_BLOG_SITE_SLUG='<slug>' \
SHOPIFY_ADMIN_TOKEN='<shopify-admin-token>' \
SHOPIFY_SHOP='<shopify-shop>' \
SHOPIFY_BLOG_ID='<shopify-blog-id>' \
SHOPIFY_API_VERSION='<shopify-api-version>' \
SEO_BLOG_SITE_ORIGIN='<origin>' \
npx --yes @wotaso/seo-blog-admin-cli publish-cms --cms shopify --site-slug '<slug>' --site-origin '<origin>' --dry-run
For a currently due approved post, --dry-run builds the destination payload without writing to the provider. It does not contact the provider or prove credentials, remote schema compatibility, deployment, or a live page; when no post is due, provider inputs are not exercised.
Scheduled runner health heartbeat
SEO_BLOG_PUBLISH_TOKEN='<tenant-token>' \
SEO_BLOG_SITE_SLUG='<slug>' \
SHOPIFY_ADMIN_TOKEN='<shopify-admin-token>' \
SHOPIFY_SHOP='<shopify-shop>' \
SHOPIFY_BLOG_ID='<shopify-blog-id>' \
SHOPIFY_API_VERSION='<shopify-api-version>' \
SEO_BLOG_SITE_ORIGIN='<origin>' \
SEO_BLOG_SCHEDULED='true' \
npx --yes @wotaso/seo-blog-admin-cli health --config seo-blog.config.json --mode cms --site-slug '<slug>' --site-origin '<origin>'
Run this from the real scheduled runner after seo-blog.config.json contains the selected connector configuration and the listed secrets are loaded. It reports configuration readiness, not a live article. The dashboard expires readiness at the returned deadline, with a 36-hour fallback when no deadline is available.
Fields and data model
- Article handle comes from the reviewed slug
- Tags and author use native Shopify article fields
- A featured image URL is mapped with descriptive alt text
Canonical and route
The Shopify online store, blog route, theme, sitemap, canonical tags, and storefront deployment remain authoritative. The publisher writes to the selected native blog rather than creating a second hosted article.
Known limits
- The Admin API token needs article and blog access for the selected shop.
- Blog IDs are GraphQL global IDs and must match the article destination.
- Theme layout and commerce-specific components are not changed by the article publisher.
Recovery
- Dry-run with the production shop hostname and Blog ID before writing.
- Read GraphQL userErrors before retrying a rejected mutation.
- Confirm the handle and parent blog when an existing article is not detected.