Skip to content

Products ​

Everything you sell lives on one screen. This page covers the Products list — columns, search, filters, bulk actions — and every field in the product editor, for both product types that have an admin interface.

Prices in examples use $. Your store's currency is set once in Ambikly → Settings → Store and every price field follows it.

The Products screen ​

Open Ambikly → Products. The list shows 50 products per page, newest first.

Toolbar ​

ControlWhat it does
SearchMatches name, sku, description and short_description. Waits 500 ms after you stop typing, then resets to page 1.
All CategoriesFilters by the product's single category.
All TypesPhysical or Digital only. No other type is offered here.
All StatusPublished or Draft.
ColumnsToggles optional columns on and off.
ExportDownloads a product CSV using the Status and Type filters currently set. See Import & export (CSV).
Add New ProductOpens the "What are you selling?" dialog.

Columns ​

ColumnShown by defaultSortableNotes
ProductYes (always)YesThumbnail, name, and the short description underneath.
SKUYesYes— when the product has none.
TypeYesYesBadge showing the stored type value.
PriceYesYesStrikes the regular price and shows the sale price in red when a sale price is lower.
StockYesYesSee the badge rules below.
StatusNoYesPublished / Draft pill.
CategoryNoNoResolved from the category list.
DateNoNoCreated date.

Your column choices are stored in your own browser under ambikly_products_visible_columns. They are per-browser, not per-user-account, and do not sync to another machine.

The Stock badge reads:

ConditionBadge
Stock tracking off, or stock status is instockIn Stock
Quantity is 0Out of Stock
Quantity is below 10Low (n)
Anything elseIn Stock (n)
Careful: the "Low" cut-off in this badge is hard-coded at 10. It ignores both the per-product low-stock threshold and the global one in Ambikly → Settings → Store. Those two values drive the low-stock alert emails, not this badge.

Row actions ​

Each row has View, Edit and Delete.

Delete asks for confirmation first. While the dialog opens, Ambikly calls GET /products/{id}/usage in the background and upgrades the message once the answer arrives: if the product appears on past orders, the dialog names the number of orders and warns that deleting it will not change those orders' totals but will break the link back to the product from them.

Deleting a product also removes its rows from every child table: pricing plans, downloadable files, attributes, attribute values, variations, grouped-product links, product meta, product relationships, product terms, reviews, bundle rows and license keys. This is not reversible.

Bulk actions ​

Select one or more rows and a bar appears under the filters.

ActionWhat it does
Set to PublishedSets status = published on every selected product.
Set to DraftSets status = draft.
Export SelectedExports only the selected product IDs to CSV.
Delete SelectedPermanently deletes the selected products and all their child rows.

Bulk delete asks for confirmation but does not run the order-usage check that a single delete does.

Creating a product ​

  1. Go to Ambikly → Products and click Add New Product.
  2. Type the product name. The field caps at 200 characters and shows a counter.
  3. Choose Physical product or Digital product.
  4. Click Continue. Ambikly creates the product immediately as a draft and opens the editor.

The product exists from that moment, as a draft. If you close the tab the draft stays in the list.

Product types ​

The ambikly_products table stores two separate fields: type is the base nature of the product, and sub_type is the variant.

typesub_typeAdmin UIHow to create it
physicalsimpleYesAdd New Product → Physical product
physicalvariableYesPhysical product, then switch Product type to "Product with variants"
digitalsimpleYesAdd New Product → Digital product
external—NoCSV import or the REST API only
grouped—NoCSV import or the REST API only
bundle—NoCSV import or the REST API only (the Bundles Pro add-on manages these)
subscription—PartialExisting rows load and re-save; there is no way to create one from the editor
Careful: Grouped and External products have no admin interface. Tab components for both exist in the plugin's source (GroupedProductsTab, ExternalSettingsTab) but nothing imports or renders them, and the Product type selector offers only "Single product" and "Product with variants". You can still create type=external and type=grouped rows by CSV import or through POST /ambikly/v1/products, and the storefront handles them: an external product renders its button_text as a link to its external_url instead of an Add to Cart button. Editing one in the admin will not show you those fields.

Switching an existing physical product between "Single product" and "Product with variants" only changes sub_type. No pricing or stock data is discarded when you switch.

The physical product editor ​

The editor is one page. The main column holds cards; four of them open as side drawers.

Product name ​

FieldTypeRequiredNotes
NameTextYesSaved to name.
Web address (URL slug)TextNoAuto-generated from the name. Made unique on save by appending -1, -2 and so on.

Product URLs are query-string based: {your shop page}?ambikly_product={slug}. There is no pretty-permalink rewrite in the free core, so changing the slug changes that query value and nothing else.

Photos ​

Up to 10 images. The first becomes the main listing image (image); the rest go to gallery, stored as a JSON array of URLs. Images come from the WordPress media library. Remove one with the × that appears on hover.

If no main image is set when you pick several at once, the first selection becomes the main image and the rest go to the gallery.

Pricing ​

FieldTypeRequiredNotes
Selling priceDecimal(10,2)Yes for simple productsSaved to price. Negative values are rejected with invalid_price.
Sale priceDecimal(10,2)NoSaved to sale_price. Must be strictly lower than the selling price or the save fails with Sale price must be lower than the regular price.

The editor shows the discount percentage live under the sale price field, and turns it into a red warning when the sale price is not lower.

A sale price is active as soon as it is set — there are no start and end dates in the free core. Product::isOnSale() passes through the ambikly_product_on_sale filter, which is how the Flash Sales Pro add-on gates a sale to a schedule.

For a variable product, the base price is optional. Each variation carries its own price. See Variations.

Description ​

FieldTypeRequiredNotes
Full descriptionRich textYes to publishSaved to description, sanitized with wp_kses_post.
Short taglineTextNoSaved to short_description. Shown on listing cards and used as the meta description fallback. A counter warns past 160 characters but does not block you.

With Ambikly Pro and the AI Descriptions add-on active, a generate card appears above the description fields.

Inventory & stock (drawer) ​

FieldStored asNotes
Track stock levelsmanage_stockOn by default. Off means the Stock status field alone decides availability.
Quantity in stockstock_quantityOnly shown when tracking is on.
Low stock alertProduct meta low_stock_thresholdPer-product override of the global threshold. Clearing it deletes the meta row and falls back to the global value.
Stock statusstock_statusinstock, outofstock or onbackorder.
When sold outNot storedSee the warning below.
Careful: the "When sold out" dropdown (Block purchase / Allow, warn customer / Allow silently) is sent on save as backorders, but there is no backorders column and nothing on the server reads the value. Backorders are not implemented in the free core. The onbackorder stock status value saves and round-trips, but it does not make an out-of-stock product purchasable.

Full behavior is on Inventory & stock.

Shipping (drawer) ​

FieldStored asNotes
Weightweight, decimal(8,2)Label reads lbs.
Length / Width / Heightlength / width / height, decimal(8,2)Label reads inches.
Shipping classNot storedSee the warning below.
Careful: two things in this drawer do not behave the way the labels suggest.

The unit labels are hard-coded to lbs and inches. The store's own weight_unit and dimension_unit (set in the setup wizard, defaults kg and cm) are ignored here. The numbers you type are stored raw, so decide on one unit and use it consistently.

The Shipping class dropdown is a fixed list of five options (No class, Standard, Express, Fragile, Oversized). It is sent as shipping_class on save, but there is no column for it and ShippingService never reads it. Choosing a class changes nothing about the rate a customer pays. See Shipping for what does affect rates.

Search engine optimisation (drawer) ​

FieldStored asFront-end effect
Meta Titlemeta_title, varchar(255)Replaces the page <title> on the product page. The field caps typing at 60 characters.
Meta Descriptionmeta_description, textPrinted as <meta name="description">, stripped of tags and trimmed to 30 words. Falls back to the short tagline when empty. The field caps typing at 160 characters.
Meta Keywordsmeta_keywords, varchar(500)None.
Careful: meta_keywords is captured, sanitized and saved, but nothing on the front end ever outputs it. It appears only in the admin product view. Treat the field as an internal note.

Ambikly also prints a <link rel="canonical"> pointing at the product's own ?ambikly_product= URL, so products are not reported to search engines as duplicates of the shop page.

Right-hand column ​

CardFieldStored asNotes
StatusLive / Draftstatuspublished or draft. Draft products 404 on the storefront.
CategoryDropdowncategory_idExactly one category per product, or none. Only appears when at least one category exists. See Categories, tags & brands.
Product code (SKU)TextskuLeave blank and Ambikly generates SKU-000123 from the new row's ID after insert. Unique across all products.
VisibilityFeatured productfeaturedPins the product to featured sections. Read by the shop grid and the featured filter.
VisibilityWhere customers can find itNot storedSee the warning below.
Careful: the "Where customers can find it" dropdown (Everywhere / Shop listings only / Search results only / Hidden) is sent as catalog_visibility, but there is no column and nothing reads it. Every published product appears everywhere. To hide a product, set it to Draft.

The digital product editor ​

A digital product uses a different layout. It has no Pricing card, no Inventory drawer and no Shipping drawer, because price and delivery both live on pricing plans.

CardPurpose
Product nameSame as physical: name and slug.
PhotosCover art or a thumbnail for the shop listing.
DescriptionFull description and short tagline, both required to publish.
Downloadable filesThe shared file pool, each file with its own version string.
Pricing plansOne or more plans, each with a price and optional recurring billing.
Search engine optimisationSame three fields as the physical editor.

The right-hand column carries Status, Category, Product code (SKU), License keys and Visibility.

Digital products never track stock: the editor sends manage_stock = 0, stock_quantity = null and stock_status = instock on every save regardless of what is in the database.

Full coverage of files, plans, limits and delivery is on Digital downloads.

Saving and publishing ​

Two buttons sit at the top of the editor, and a save bar slides in as soon as the form is dirty.

ButtonEffect
Save draftSaves with status = draft. Skips every content check except the name.
Publish / Save changesSaves with status = published after running the checks below.

Publishing is blocked, with a message naming the card to fix, when:

  • The name is empty.
  • A simple physical product has no price, or a price of 0 or less.
  • A digital product has no pricing plan with a price above 0.
  • A variable product has no attributes or no variations.
  • The full description is empty.

A variable product's own base price is deliberately not required.

Drafts are exempt from all of these except the name, so you can park incomplete work.

After the first publish of a new product the URL switches to edit mode and the product ID appears in the address bar. Leaving the page with unsaved changes prompts for confirmation.

Fields the editor does not expose ​

These columns exist on ambikly_products and are accepted by the REST API and the CSV importer, but have no field in the admin editor.

ColumnDefaultWhat it is for
tax_classstandardWhich tax-rate class applies. See Tax.
tax_statustaxableWhether tax applies at all.
external_urlnullDestination for an external product's buy button.
button_textBuy ProductLabel on that button.
billing_period, billing_cycle, trial_period, subscription_lengthnull / 1 / 0 / nullLegacy product-level subscription terms. Digital products use per-plan subscription settings instead.
download_limit, download_expiry_daysnullPer-product download caps. See Digital downloads.

Saving a product from the admin editor does not clear these. The form sends null for values it has no field for, and the update path skips any key whose value is null, so existing values survive an admin save.

Product meta ​

Arbitrary key/value data can be attached to a product through three routes.

MethodRoutePermission
GET/ambikly/v1/products/{id}/meta/{key}Manage store
POST/ambikly/v1/products/{id}/meta/{key}Manage store
DELETE/ambikly/v1/products/{id}/meta/{key}Manage store

Keys must match [a-z0-9_-]+. Values are stored as strings in ambikly_product_meta. All three verbs require the manage-store capability — there is no public read.

The free core itself stores low_stock_threshold here. Pro add-ons use it for their own per-product flags.

REST routes for products ​

MethodRoutePermission
GET/ambikly/v1/productsView store
GET/ambikly/v1/products/{id}View store
POST/ambikly/v1/productsManage store
PUT/ambikly/v1/products/{id}Manage store
DELETE/ambikly/v1/products/{id}Manage store
GET/ambikly/v1/products/{id}/usageManage store
POST/ambikly/v1/products/bulk-deleteManage store
POST/ambikly/v1/products/bulk-statusManage store

The list endpoint accepts search, category_id, type, status, per_page (default 50), page, orderby (id, name, sku, price, stock_quantity, status, type, created_at, updated_at) and order. Pagination comes back in the body as total, page, per_page and total_pages — there are no X-WP-Total headers.

Full details are in the Endpoint reference.

Common errors ​

CodeHTTPCause
missing_name400No product name.
invalid_price400Negative price.
invalid_sale_price400Negative sale price, or a sale price that is not lower than the regular price.
duplicate_sku400Another product already has that SKU.
invalid_category400category_id does not match an existing category.
product_not_found404No product with that ID.

Next ​