Skip to content
Stone & Water
Manual · Current version

PIM for Shopware 6 — Manual

This page bundles all functions of the PIM plugin for Shopware 6 at a glance. It serves as a compact reference — for detailed step-by-step guides with screenshots, please use the dedicated documentation pages for each area.

The PIM plugin is compatible with Shopware 6.5, 6.6 and 6.7.

System requirements

  • Shopware: 6.5, 6.6 or 6.7
  • PHP: 8.2 or newer
  • Database: MySQL 8 or MariaDB 10.11
  • Memory: Shopware's standard recommendation (256 MB+)
  • Permissions: Shopware admin access as administrator role
Note: The plugin uses only official Shopware data models and APIs.

Installation

Installation via Shopware Store or manual upload.

Via Shopware Store

  1. In Shopware admin, go to Extensions → Store and search for "PIM for Shopware"
  2. Load the plugin — it then appears under Extensions → My extensions
  3. Click Install, then Activate

Activate plugin

Activation registers ACL permissions, menu items in the sidebar, and builds the initial config matrix with defaults.

Open PIM

After activation the PIM menu item appears in the Shopware admin sidebar.

Config matrix

The config matrix is the central control element under Settings → System → PIM configuration. It controls:

  1. Visible fields in listing
  2. Editable fields in bulk-edit
  3. Active languages
  4. Default patterns for variant generator
  5. AI provider configuration
  6. Export settings for CSV
  7. Visible fields in the Quickview modal

Section order via drag-and-drop

The order of sections in the product detail view (master data, prices, media, SEO, properties, cross-selling, …) can be freely set via drag-and-drop. The same applies to the sections in the variant detail modal — both are configured in their own tabs of the config matrix.

Sections without active fields are automatically hidden — no empty accordion headers.

Gross/net toggles for all price types

All four price types can be shown/hidden independently for gross and net in the config matrix — both for master articles and variants:

  • Sales price gross / net
  • Purchase price gross / net
  • List price / RRP gross / net
  • Lowest 30-day price (Omnibus) gross / net

This allows pure gross maintenance, pure net maintenance, or mixed display — matching the shop's default tax logic or the maintainer's preference. Existing user configurations with the old single toggles remain valid via fallback logic — no migration required.

SEO URL system — two generators with a custom field as bridge

The SEO URL system works in two clearly separated steps that interact via a canonical custom field. The advantage: the final URLs come from Shopware's own SEO template and survive every reindex — even if Shopware fully reindexes the catalogue, your URLs stay intact.

Step 1 — "Generate URL in custom field" (token → field)

A token pattern (e.g. {mainCategoryPath}/{name}) is resolved variant- and language-accurately and written to the per-shop custom field staw_pim_canonical_<shop>. Available in two ways:

  • Bulk run: button in the SEO tab opens the modal with channel/language selection (grouped by shop, accordions, "select/deselect all" per group) and progress display
  • Per product: "Generate from pattern" button directly in master data and variants — fills the input field, then save normally

Available tokens as clickable chips: {name}, {productNumber}, {manufacturer}, {category}, {categoryPath}, {mainCategory}, {mainCategoryPath}, {options}, {properties}, {tags}, {ean} plus custom field tokens. The "field pattern" is its own input, separate from the step-2 Twig URL pattern.

Step 2 — "Generate SEO URLs" (Twig → database)

A Twig pattern reads the custom fields and is set as Shopware's native SEO URL template (seo_url_template) per sales channel. Reindexing runs through Shopware's own SeoUrlGenerator — Shopware generates the URLs itself from the custom field. Typical pattern for migrations:

{% if staw_url_product_detail %}{{ staw_url_product_detail|raw }}{% else %}{{ product.customFields.staw_pim_canonical_shop|raw }}{% endif %}

Migrated products keep their existing URL, new products use the field filled by step 1. Changed paths remain as 301 redirects — no SEO loss, no 404 for existing links.

Migrated field language-strict: the migrated field is checked strictly in the current language, without Shopware's translation inheritance — values from another language don't win.

Pattern editor with textarea, pencil and Twig syntax check

The pattern input is a textarea with auto-height — for long patterns with {% if %} conditions, the entire logic is visible. Per pattern:

  • Pencil icon to edit — opens a large editor with variable chips
  • Context-aware variable chips: token chips for step 1, official Shopware SEO Twig variables (product detail page) for step 2. Fields are inserted with |raw directly
  • Live Twig syntax check: invalid Twig is flagged in red, save is blocked
  • Mix warning: when {tokens} and Twig ({% %}/{{ }}) appear in the same pattern, the editor warns — it doesn't work because Shopware slugifies the Twig output and strips token braces. Recommendation: pure Twig or pure token pattern

Custom pattern per shop — for both generators

The per-sales-channel pattern editor is available for both generators: step 1 can get its own token pattern per channel, step 2 its own Twig pattern. Shop patterns are a list: each shop with its own pattern shows name + pattern — editable via pencil or removable via trash. "Add pattern for shop" opens the editor modal with channel selection. Shops without their own pattern use the default pattern.

The generation modal

Both generators open a guided modal (in PIM CI with indigo accents):

  1. Pick sales channel + languages — all active channels, grouped by shop as cards with language accordions below (initially collapsed, nothing preselected). Per group "select/deselect all" with counter, plus a global "select all" button. Per channel badges: product count (only products actually visible in the channel, incl. variants) and missing-URL count.
  2. Options:
    • "Keep old URLs as 301" — changed paths remain as redirects
    • "Only generate missing SEO URLs" — existing/migrated URLs stay untouched
    • "Remove all product URLs (reset)" — deletes all SEO URLs of the selected channels/languages (incl. Shopware's global detail URLs of that language) and rebuilds fresh. The other options visibly switch to OFF
  3. Preview — picks sample products that are visible in the channel and whose pattern resolves; up to three real example URLs, long URLs wrap, box is scrollable.
  4. Dry-run or generation — the dry-run shows the complete run without writing. Result cards colour-coded: new = green, change = blue, skipped = grey, warning = amber, error = red.

The progress bar shows a percentage with indigo gradient. Generation runs chunked — even tens of thousands of products without timeout.

Result report and conflicts

  • Written / skipped / redirects as counters
  • "N without rendered path" — products whose pattern outputs nothing (e.g. migration field and canonical field both empty). Makes it immediately clear why nothing was written
  • Conflicts with product numbers instead of internal IDs. Paths already taken by another route (e.g. a category with the same slug) are cleanly skipped and reported as "path already taken elsewhere" — no duplicate-key abort
Important: the same URL in different shops is not a conflict — uniqueness applies per shop + language. Fix for real conflicts: make the pattern more unique, e.g. {mainCategoryPath}/{name}-{options}.

Slug handling: umlauts, slashes, dots

  • Umlauts and special characters (also in static pattern text like a literal "für/") are converted: ä→ae, ö→oe, ü→ue, ß→ss; "&" and spaces become the separator
  • Slashes and dots are preserved — category names with "/" and article numbers/names with "." (e.g. .html suffixes) pass through unchanged
  • Twig |raw automatic: Shopware's SEO environment slugifies every Twig output (incl. slashes → "-"). Bare outputs of path fields automatically get |raw injected in all generation paths
  • Preview and server generation behave identically — what the preview shows is what gets written
  • Safety net: empty canonical field → fallback to the product name instead of an empty path

Language fallback for multi-language shops

Generation consistently uses the channel-/language-specific values (name, manufacturer, category, variant options). Fallback chain: requested language → parent language → system; empty or inherited translations are skipped. Applies to token and Twig generation — no accidental default language in foreign-language URLs.

Variants: unique URLs

Both generators process parent and variants. Inherited fields are resolved from the parent (incl. translated customFields with inheritance). The tokens {options}, {properties} and {tags} deliver language-translated values — a pattern like {mainCategoryPath}/{name}-{options} produces a unique URL per variant and language, no duplicate paths between variants of the same parent.

Deterministic category path

{mainCategoryPath}/{categoryPath} use the main category of the respective sales channel. If none is set, the fallback prefers the deepest assigned category (longest path) — deterministic instead of arbitrary. With an empty category.path column (indexer backlog after imports), the ancestor chain is reconstructed via parent_id.

UX note: the SEO accordions (URL pattern, options, generate SEO URLs) start collapsed by default. Reload on …/config/seourl reopens the SEO tab.

Default tax rate for new products

When creating a new product, the first tax rate from the Shopware system is automatically preselected (sorted by position ASC). Both taxId and taxRate are set.

Validation modal with scroll-to-section

Clicking Save while required fields are empty: instead of a wall of warning banners, a modal opens listing all errors. Clicking an error jumps directly to the relevant section.

Permissions (ACL)

The plugin registers a dedicated permission group "StawPim (products)" in the Shopware ACL system. Found under:

Settings → Users & Permissions → Roles → pick or create a role → group "Catalogues" → "StawPim (products)"

Four roles per user role

  • staw_pim.viewerView: open the PIM area, list products, see the configuration matrix. Required for all other roles.
  • staw_pim.editorEdit: inline edit, bulk-edit, Quickview modal, AI text generation. Requires viewer.
  • staw_pim.creatorCreate: create new products, CSV import, variant generator. Requires viewer + editor.
  • staw_pim.deleterDelete: delete products. Requires viewer.

Role-based menu visibility

Without the "StawPim: View" permission, the menu items are not visible — dashboard, products and configuration matrix don't appear for unauthorised users at all. The automatic redirect from the Shopware default product list to the PIM list also respects the permission.

Feed Generator separately releasable

In the superadmin area "Features for normal users" there's a dedicated "Feed Generator" toggle — the Feed Generator button (in the product list) can be enabled/disabled for non-superadmin users independently of CSV import/export. Default: active. Superadmins always see the button.

After the update: Non-admin users need to have the new "StawPim: View" permission assigned to their role once. Previously access was implicitly granted via generic product permissions (product.viewer etc.) — now it's explicit. Admin roles continue to see everything.
Underlying Shopware permissions: The viewer role internally grants product.viewer, custom_field_set:read, sales_channel:read, language:read, product_stream:read, tag:read, delivery_time:read, unit:read, tax:read. editor grants product.editor, creator grants product.creator, deleter grants product.deleter — all via the official Shopware Privilege API.

CSV import tab

Additional restriction: For security reasons, the import tab in the CSV modal is additionally restricted to superadmins — even if the role has creator. Reason: CSV import can massively change the catalogue and should only be done by experienced admin users.

Languages

PIM supports all languages configured in Shopware. Languages become visible/editable when marked as active in the config matrix.

Listing structure

The central product listing with filter bar, sortable column headers, data rows with variant expansion, footer toolbar and bottom save bar.

Filters with AND/OR

  • 9 comparison modes: contains, does not contain, equals, not equal, starts with, ends with, is empty, is not empty, in list
  • AND/OR logic — also nested
  • Variant-aware — considers parent and variants

Configure columns

Visible columns are configurable per user — add via plus icon, reorder by drag-and-drop, resize by dragging the column edge.

Filter and column presets

Personal, shared and system presets. Activate via click, search via keyboard shortcut.

Inline editing

Fields can be edited directly in the listing by clicking. Stock, price, EAN, manufacturer number and weight inline editable — also for variants. After save the value is verified (read-back). If Shopware discards the value, a warning appears instead of falsely reporting success.

Keyboard shortcuts: Enter confirms, Esc cancels, Tab jumps to the next field.

Quickview modal

Directly from the listing, a Quickview modal can be opened per product — via the Quickview icon in the row. It shows the most important master data compactly for direct editing, without switching to the full detail view.

  • Master data: SKU, name, EAN, MPN, active status
  • Prices: gross/net, purchase price (gross + net), omnibus price
  • Stock & shipping: stock, restock time, closeout, free shipping
  • Order quantities: min/max/step
  • Description as textarea
  • SEO: meta title, meta description, keywords

Header layout

The modal header shows the variant name in front (large and dark), the SKU as secondary info behind it (small, grey) — same as the master variant view. This makes it immediately clear which variant is being edited during variant maintenance.

Uniform input fields

All input fields in Quickview follow the same structure: label on top, input below (42 px height) — consistent with the rest of the plugin. This applies to text fields, number fields, selects and toggles.

Expand all / collapse all

The modal header has an Expand all / Collapse all button — same as in the master data detail view. This opens or closes all accordions in one step.

Which fields are visible is controlled in the config matrix under "Quickview". Sections without active fields are hidden automatically.

Variant display

Variant products appear in the listing as a parent row. Click the plus icon to expand variants inline.

Image upload via drag & drop

In master data and in the variant view, the "Images/Media" section has a drag-&-drop zone (below the images). Drop files or click to open the file dialog — both work, with progress display.

  • Uploads go to the Shopware media library (product folder) and are immediately assigned to the product
  • The first image automatically becomes the cover if none is set yet
  • Variants: an uploaded image becomes the variant's own image and overrides the inherited one. Removing the own image restores inheritance from the main product — both stay possible at any time

Approval workflow — "In progress" status

In addition to approve/reject/submit, there's the "In progress" status that editors can set themselves on a product — signalling to the team that someone's working on it. The status is reflected everywhere:

  • Detail view: status badge + button to set it
  • Product list: filter and status indicator (indigo)
  • Settings: approval statistics count "In progress" too

Category assignment with chips

Assigned categories are listed as removable chips below the category tree (small × to remove). Instantly visible which categories are selected — without searching the tree.

Bulk-edit — overview

Allows changing fields on any number of selected products in a single operation. The operation runs in two phases (Snapshot + Apply) with live-progress indicator (counter, phase, ETA) — cancellable at any time.

Editable fields

Master data

  • Name, description (per language)
  • Meta title, meta description, keywords
  • Manufacturer, EAN, SKU
  • Product unit (piece, litre, kilogramm, metre, …) — dedicated bulk action

Prices and base price

  • List price and RRP, tier prices
  • Purchase price gross + net as two separate actions — the other value is automatically calculated via the product's tax class
  • List price/RRP, lowest 30-day price (Omnibus)
  • Base price (dedicated bulk action): content quantity + base unit
  • Re-assign tax rate (gross stays, net is recalculated)

Stock and shipping

  • Stock, delivery time, free shipping flag, weight, height, width, length

Sales channels and categories

  • Sales channel visibility, main category, additional categories, cross-selling

Properties and custom fields

  • Properties (assign and remove), custom fields of all types, tags
Combine multiple actions: In one bulk run, any number of actions can be performed at once.

Complete filter display before every operation

Before every bulk-edit, the PIM shows all active filters from the selected preset as readable chips: manufacturer, categories, tags, properties, stock range, price range, weight range, date ranges, visibility, tax class, delivery time, dynamic product groups, sales channel, EAN status, closeout, free shipping and SEO meta status. IDs are resolved to readable clear names (e.g. sales channel name instead of UUID). "No filters active" is marked with red border — an intentional warning against accidental bulk operations.

Language selection for translatable fields

Translatable bulk fields show a language dropdown as soon as a value is entered. The value is set in the default language and additionally written to every selected language — one action, multiple languages.

Fields with language selection:

  • SEO tab: meta title, meta description, SEO URL
  • Custom fields: all custom fields marked as translatable in Shopware
  • Shipping tab: packaging unit (singular/plural) — the only translatable field in the shipping section

Fields deliberately without language selection:

  • Product unit / unit of measure: it's only a reference to a unit (piece, litre, kg) — the translation lives on the unit itself, not on the product
  • Language-independent fields: price, stock, EAN, weight, manufacturer, active status, dimensions, delivery time — these exist only once per product
Multiple languages at once: A bulk action "Set packaging unit" with languages "German + English + French" writes the value to all three languages — no triple execution needed.

Data inheritance parent → variants

A dedicated bulk action transfers fields from the parent product to all its variants:

  • Description and meta texts
  • Apply tier prices to all variants
  • Transfer cross-selling streams
  • Pass images and media gallery to variants
  • Take over SEO fields (title, description, keywords)

Snapshot & revert

Every bulk-edit stores a snapshot of the previous values automatically. Kept for 30 days. Overview under PIM → Snapshots.

Caution: Three fields are not snapshot-capable: SEO URL (generated), tier prices → variants, cross-selling → variants.

Live preview

Before saving, a table shows current value, new value, diff marker and notes for non-editable fields.

CSV export

  • Columns freely selectable
  • Separator: comma, semicolon, tab
  • Decimal separator: dot or comma
  • Encoding: UTF-8 (with BOM option)
  • Variant export per profile or globally
  • Preset profiles: master data, SEO, images, prices & stock, properties & custom fields, cross-selling, translations

"Unit (name)" column

In addition to the unit ID (UUID), the product unit is exported as a readable name (e.g. "Litre", "Kilogramm", "Piece").

CSV import

Reads a file and creates new products or updates existing ones. Match by SKU, ID or EAN.

"Unit" auto-detection

The importer recognises both "Unit (name)" and "Produkteinheit" as column headers automatically.

Automatic lookups

Missing entities are created automatically. For variants, parent IDs can also be resolved via SKU or EAN.

Security: The import tab is only accessible to super admins.

Data type detection

  • Boolean: 1/0, true/false, yes/no, active/inactive
  • Date: ISO notation and German notation
  • Number: comma or dot as decimal separator
  • Array: pipe separator for multi-select
  • JSON: for complex fields

Importable and exportable fields

Master data

  • productNumber — SKU (match key)
  • name, description — per language
  • ean, manufacturerNumber, manufacturer
  • taxRate, active, markAsTopseller, isCloseout, shippingFree

Prices

  • price, price_net, listPrice, purchasePrice
  • tier_*, purchaseUnit, referenceUnit
  • unitId / Unit (name) / Produkteinheit

Stock and shipping

  • stock, minPurchase, maxPurchase, purchaseSteps
  • deliveryTime, restockTime
  • weight, width, height, length

SEO, categories, variants, properties, custom fields, images, cross-selling, tags

  • metaTitle, metaDescription, keywords
  • categories, visibilities
  • parentId, mainVariantId, options
  • properties, cf_*, cover, images, crossSellings, tags

Export only

  • createdAt, updatedAt, variant count, sales, ratingAverage, availableStock

Feed Generator — automatic URL feeds

Via the Feeds tab you provide automatically updated URL feeds — e.g. for Google Shopping, price comparison portals or ERP connections. A feed delivers product data under a unique URL with token authentication.

Create feed from template or profile

At the top of the Feeds tab there's the "Create feed from template / profile" selector. With this you activate a new feed in one click:

  • Pick a built-in template — master data, prices & stock, SEO, images, variants, full export: A saved export profile with the matching field selection is created automatically, the feed activated, a token generated. The profile created from the template is named e.g. "Master data (Feed)".
  • Pick an existing profile — Your own export profiles (saved in the export tab) can be activated directly as a feed.
Multiple feeds per profile: Feeds are decoupled from the source profile — you can create any number of feeds for the same profile. Example: a "Master data" profile as the basis for multiple feeds with different filter templates per sales channel or target market.

Accordion list with status, chips and actions

All feeds and all custom export profiles appear as a compact list. Per row, you see:

  • Name · renamable
  • Status pill · "feed active" (green) or "no feed" (grey)
  • Feed URL preview · the tokenised URL for active feeds
  • Filter template chip · the chosen filter template or "no filter"
  • Product count chip · determined live from the catalogue
  • Pencil icon on the right (opens/closes the editor) and trash icon (deletes with confirmation)

Clicking the row reliably opens and closes the editor — a chevron on the right shows the state and rotates on opening. The trash button reacts separately (preventing accidental open/close).

Editor with renaming, mode, filter template

The expanded editor offers all configuration options per feed:

  • Name field — rename the feed (must be unique; collision is rejected)
  • Activate toggle — turn feed online/offline
  • Mode — XML, CSV, TSV or JSON
  • Filter template — selection from saved filter templates
  • Feed URL — ready to copy
  • Token — show or regenerate

Filter templates — what's applied, what's deliberately not

Instead of simple filter checkboxes, you pick a saved filter template in the feed — the same one you use in the listing or for bulk-edit.

Applied in the feed (reliably mappable server-side): active status, stock (min/max), manufacturer, category, sales channel.

Deliberately NOT applied in the feed: quality and completeness criteria (e.g. "missing images", "incomplete meta data", "no description", "SEO score < X"). These evaluations are calculated live in the listing and cannot be reliably mapped server-side in the feed context.

Why this separation: If the feed silently applied quality criteria, your ERP would receive a silently distorted product set. With the clear separation, you know exactly: filter template defines which products, the feed delivers those products.

Migration of old feeds

Automatic & non-destructive: If you previously had feeds attached directly to an export profile (with token/URL), these are automatically migrated into the new list on first load. Existing feed URLs in your ERP, Google Shopping account or at price comparison portals remain valid — no re-configuration required.

Token and URL format

Each feed gets a unique token. The URL has the format:

  • https://your-shop.com/staw-pim/feed/{token}.xml
  • https://your-shop.com/staw-pim/feed/{token}.csv
  • https://your-shop.com/staw-pim/feed/{token}.json

The regenerate token button creates a new token — the old URL becomes invalid. Useful when a feed link has been leaked publicly.

Backend & streaming performance

The FeedExportService is built for large catalogues. Four performance layers work together:

  • DBAL streaming in 2,000-batches — data is emitted in chunks via PHP generator (yield) instead of kept entirely in memory. Memory usage is independent of catalogue size.
  • Keyset pagination on product_number (unique, indexed column) instead of LIMIT/OFFSET — output time stays linear, even for very large catalogues.
  • gzip compression server-side via gzencode(), when the client sends Accept-Encoding: gzip. Feed CSVs compress ~80–90 % — drastically shorter transfer.
  • File mode for the largest catalogues: a scheduled task (every 15 min) atomically writes the file to var/staw-pim-feeds/ via Flysystem. On request, the pre-generated file is served — no DB load on every poll.

Additionally: @ini_set('memory_limit', '1024M') defensively in the endpoint — wide column selections with dozens of custom fields generate cleanly. Filter criteria (manufacturer, category, stock range) are applied server-side in SQL (incl. variant inheritance to the main article) — no data roundtrip into the Vue layer.

Graceful fallback in "File" mode: If the cron file doesn't exist yet (e.g. directly after creating a new feed), the controller automatically falls back to live generation. You don't have to wait for the cron to run the first time.
Security: Feed URLs are tokenised and not publicly indexable. Still, don't share them publicly — anyone who knows the token sees the product data of the feed.

Variant generator — property selection

Creates variants from property combinations automatically. Visual selection of all properties with grouped values. Live preview of combinations.

Unified search

One single search at the top filters properties and options simultaneously. Type "red" and all property groups with the option "red" stay visible while matches on the right are highlighted.

Patterns for SKU and name & pattern accordions

Available variables

  • {base}, {property:Colour}, {counter}, {counter:03}

Pattern accordions

Instead of raw inputs side by side: two dedicated accordions — one for the SKU, one for the variant name. Collapsed they show the current pattern as a code chip; expanded the input appears with clickable variable chips.

Variant matrix · Bulk prices and stock

The variant matrix lays all variants in a stacked table. Each cell offers price and stock for direct editing.

  • Inline edit for price, stock, EAN, MPN
  • Property sorting via drag-and-drop
  • Optional: apply parent values to empty cells

Safe deletion

Checks for open orders.

  • Mode "Safe" (recommended): Variants with open orders are not deleted, only deactivated
  • Mode "Complete": All variants deleted

AI text generation — providers and models

  • Anthropic Claude: Haiku 4.5, Sonnet 4.6, Opus 4.6 / 4.7
  • OpenAI ChatGPT: GPT-4o Mini, GPT-4o, GPT-4.1 Mini, GPT-4.1

Set up API key

  1. Create API key at console.anthropic.com or platform.openai.com
  2. Enter in Config matrix → Translations
  3. "Test connection" button to verify
  4. Pick model and tone
  5. "Enable bulk" to activate in bulk-edit

What can be generated

  • Description (HTML), meta title, meta description, keywords

Style templates

5 predefined: Professional, casual-modern, premium/luxury, technical, emotional.

Performance

  • Browser-native virtualisation via content-visibility: auto
  • Server-side filtering, lazy loading
  • Bulk operations in batches with progress
  • Minified bundle — ~23% smaller

Bulk edit & import: async indexing

  • Queue indexing instead of sync: bulk-edit product writes default to Shopware's async queue indexing (header use-queue-indexing) instead of synchronous in-request indexing. The write batch size is 25 (previously 10) — large bulk runs complete several times faster. Configurable via bulkIndexingBehavior: use-queue-indexing | disable-indexing | sync.
  • CSV import without full reindex: imports also use queue indexing — only the imported products are reindexed asynchronously. The previous full-catalogue reindex after every import is gone (only runs with importIndexingMode = 'disable'). Modes: queue | disable | sync.
  • Batched requests: audit-log writes are saved as one batch every 600 ms (plus on page leave); bulk approvals run through a batch endpoint (one request per 200 products); bulk translations and approval/audit writes use INSERT … ON DUPLICATE KEY UPDATE.
  • Batched variant deletion: one IN delete instead of one statement per variant, with per-ID error feedback and automatic single-delete fallback for e.g. foreign-key locks.
  • Lazy snapshots: bulk-edit snapshots and undo data (potentially several MB) are loaded only once per session.
  • Stale-response guard: rapid filter/page changes can no longer overwrite newer results with older ones.

Diagnostics & stability

  • Session error log: the last 50 errors are kept in window._stawPimErrLog — previously silent error paths (audit flush, batch approvals, snapshot loading) now log failures, so problems are diagnosable via the browser console even without server log access.
  • Internal test suite: lightweight test runner (no PHPUnit needed) checks SEO fallback logic, snippet consistency de-DE ↔ en-GB and version consistency on every release.

Troubleshooting

Listing does not load

Clear cache, check browser console, check PHP memory limit (512 MB recommended).

CSV import fails

Check encoding (UTF-8), separator, PHP limits.

AI generation fails

Test API key. Anthropic: top up credit. OpenAI: check billing status.

Contact & support