# Togglix Variation Switcher for WooCommerce — Documentation

This document describes **every option and feature currently available** in the plugin, for use in WooCommerce Marketplace listing documentation and customer support.

## Overview (what the plugin does)

Togglix Variation Switcher lets shoppers **edit variable product variations directly from Cart and Checkout**, without removing the item and re-adding it from the product page.

Key capabilities included in this build:

- **Cart + Checkout editing** for variable products (classic shortcode templates and WooCommerce Blocks)
- **Modal/popup variation selector** with optional live preview
- **Smart variation availability** (disable invalid/out-of-stock combinations)
- **Inventory-aware switching** (server-validated during update)
- **Cart-line accuracy** using WooCommerce **cart item key** (important when the same parent product appears multiple times)
- **Merchant rules** (role, coupon, include/exclude products/categories/tags)
- **Compatibility controls** (profile presets + safe mode + Blocks toggle)
- **Analytics** (event tracking, date range filtering, CSV export, conversion rate, daily chart, failure reasons)
- **Per-product overrides** (disable switcher, custom Edit label)

## Where settings live

- **Global settings page**: `WooCommerce → Variation Switcher`
  - Tabs: **General**, **Design**, **Behavior**, **Compatibility**, **Rules**, **Analytics**
- **Per-product options** (variable products only): `Products → Edit product → Product data → General`

## Global settings (every field, in detail)

All global settings are stored in one option:

- **Option key**: `togglix_vsfw_settings`

### General tab

#### Enable plugin
- **Setting key**: `enable_plugin` (boolean)
- **Default**: enabled
- **What it does**: Master on/off switch. When disabled:
  - Frontend scripts/styles are not loaded.
  - The popup HTML is not printed in the footer.
  - The Edit link behavior becomes inactive.

#### Update button label
- **Setting key**: `update_button_label` (string)
- **Default**: `Update`
- **Where it appears**: Label of the main action button inside the popup.

#### Edit link label
- **Setting key**: `edit_link_label` (string)
- **Default**: `Edit`
- **Where it appears**:
  - On Cart/Checkout line items as the link to open the popup.
  - Can be overridden per product (see “Per-product options”).

---

### Design tab

#### Popup width (px)
- **Setting key**: `popup_width` (integer)
- **Default**: `800`
- **Allowed range**: 320–1200
- **What it does**: Controls the maximum width of the popup container.

#### Primary color
- **Setting key**: `primary_color` (hex color)
- **Default**: `#007bff`
- **UI control**: WordPress color picker + text input
- **What it does**: Controls the primary color used for the Update button background.

---

### Behavior tab

#### Variation preview
- **Setting key**: `show_variation_preview` (boolean)
- **Default**: enabled
- **What it does**: Shows/hides the preview panel inside the popup.
- **Preview contents**:
  - Price (HTML from WooCommerce)
  - SKU
  - Stock/purchasability label
  - Variation image (if present)

#### Show close button
- **Setting key**: `show_close_button` (boolean)
- **Default**: enabled
- **What it does**: Shows/hides the “X” close button in the popup.

#### Close on overlay click
- **Setting key**: `close_on_overlay` (boolean)
- **Default**: enabled
- **What it does**: If enabled, clicking outside the popup (on the overlay) closes the modal.

#### Auto reload delay (ms)
- **Setting key**: `auto_reload_delay` (integer)
- **Default**: `2000`
- **Allowed range**: 0–10000
- **What it does**: Wait time after a successful update before the popup closes and the page refresh behavior runs.

#### Inventory-aware switching
- **Setting key**: `enforce_inventory_rules` (boolean)
- **Default**: enabled
- **What it does (frontend selection)**:
  - When enabled, the dropdown availability logic only allows combinations that match a variation which is:
    - purchasable (`is_purchasable`), and
    - in stock (`is_in_stock`) **or** allows backorders (`backorders_allowed`)
- **What it does (server-side update validation)**:
  - Before updating the cart, the plugin validates again and blocks updates to variations that are not purchasable or are out-of-stock with no backorders.
- **Why it matters**: Prevents “switch to an invalid/out-of-stock variation” errors and reduces checkout friction.

---

### Compatibility tab

This tab controls **where** the plugin runs (Cart vs Checkout), **how** the page updates after switching (partial refresh vs reload), and **how** the Edit link is injected (Blocks filter vs PHP classic templates).

#### Compatibility profile
- **Setting key**: `compatibility_profile` (string enum)
- **Default**: `auto`
- **Available values**:
  - **Auto** (`auto`): Uses the options below as-is.
  - **Classic-first** (`classic`): Forces **Blocks integration off** (uses PHP/cart template approach).
  - **Blocks-first** (`blocks`): Forces **Blocks integration on** (uses WooCommerce Blocks filter).
  - **Safe** (`safe`): Same behavior as Safe mode preset (full reload, no preview, no Blocks).
- **What it does**: Applies **runtime-only** overrides to reduce conflicts. It does not delete your saved options; it changes effective behavior while the profile is active.

#### Enable on Cart page
- **Setting key**: `enable_on_cart` (boolean)
- **Default**: enabled
- **What it does**: Enables the plugin behavior on the Cart page.

#### Enable on Checkout page
- **Setting key**: `enable_on_checkout` (boolean)
- **Default**: enabled
- **What it does**: Enables the plugin behavior on the Checkout page.

#### Use partial refresh after update
- **Setting key**: `use_partial_refresh` (boolean)
- **Default**: enabled
- **What it does**:
  - If enabled, after a successful update the plugin tries to refresh key cart/checkout areas via AJAX (without a full page reload).
  - If replacement fails (no matching selectors found), it falls back to a full reload.
- **Important**: Safe mode and the “Safe” compatibility profile disable partial refresh.

#### Safe mode (fallback)
- **Setting key**: `safe_mode` (boolean)
- **Default**: disabled
- **What it does (effective runtime behavior)**:
  - Disables **variation preview**
  - Forces **full page reload** instead of partial refresh
  - Disables **Blocks integration** (classic only)
- **When to use**: If a theme or plugin causes conflicts with Blocks filters, scripts, or AJAX refresh logic.

#### WooCommerce Blocks integration
- **Setting key**: `enable_blocks_integration` (boolean)
- **Default**: enabled
- **What it does**:
  - If enabled, the plugin uses `registerCheckoutFilters` in WooCommerce Blocks to inject the Edit link for block-based Cart/Checkout line items.
  - If disabled, the plugin uses a PHP filter for classic templates instead:
    - `woocommerce_cart_item_name` filter appends the Edit link in classic Cart/Checkout templates (shortcodes).
- **Notes**:
  - Safe mode and the “Classic-first/Safe” profiles effectively turn Blocks integration off.
  - The plugin adds `wc-blocks-checkout` as a JS dependency when available, so Blocks APIs load before filter registration.

#### Diagnostics (Compatibility tab section)
On the Compatibility tab, the plugin renders a **Diagnostics** report and a **Copy report to clipboard** button.

The report includes:
- WordPress version, WooCommerce version, plugin version
- HPOS status (custom order tables)
- Theme name + stylesheet
- Saved settings (safe mode, compatibility profile, inventory rules, Blocks integration, partial refresh, preview)
- Effective settings after applying profile + safe mode overrides
- Active plugins list (up to 60 entries, then “and N more”)

This report is meant for:
- Marketplace support tickets
- Conflict diagnosis
- Customer troubleshooting

---

### Rules tab (merchant restrictions)

Rules determine when shoppers are allowed to use the variation switcher for a given product.

Rules are checked server-side in `can_edit_product()` and applied to:
- Loading variations (opening the popup)
- Updating the variation in the cart

#### Disable when coupon applied
- **Setting key**: `disable_when_coupon_applied` (boolean)
- **Default**: disabled
- **What it does**: If the cart already has any applied coupons, variation editing is blocked.
- **Why it matters**: Prevents coupon recalculation surprises (some stores prefer “no changes once coupon is applied”).

#### Allowed user roles
- **Setting key**: `allowed_user_roles` (array of role slugs)
- **Default**: empty (allow all, including guests)
- **What it does**:
  - If empty: Everyone can edit variations (including guests).
  - If roles are selected: Only logged-in users whose role matches can edit variations.

#### Include products
- **Setting key**: `include_product_ids` (array of product IDs)
- **Default**: empty
- **What it does**: If non-empty, only these products are eligible for variation switching.
- **UI**: WooCommerce admin product search (`wc-product-search`)

#### Exclude products
- **Setting key**: `exclude_product_ids` (array of product IDs)
- **Default**: empty
- **What it does**: These products are never eligible for switching.
- **UI**: WooCommerce admin product search (`wc-product-search`)

#### Include categories
- **Setting key**: `include_category_ids` (array of term IDs)
- **Default**: empty
- **What it does**: If non-empty, only products in these categories are eligible.
- **UI**: WooCommerce enhanced select (`wc-enhanced-select`)

#### Exclude categories
- **Setting key**: `exclude_category_ids` (array of term IDs)
- **Default**: empty
- **What it does**: Products in these categories are never eligible.
- **UI**: WooCommerce enhanced select (`wc-enhanced-select`)

#### Include tags
- **Setting key**: `include_tag_ids` (array of term IDs)
- **Default**: empty
- **What it does**: If non-empty, only products with these tags are eligible.
- **UI**: WooCommerce enhanced select (`wc-enhanced-select`)

#### Exclude tags
- **Setting key**: `exclude_tag_ids` (array of term IDs)
- **Default**: empty
- **What it does**: Products with these tags are never eligible.
- **UI**: WooCommerce enhanced select (`wc-enhanced-select`)

---

### Analytics tab (reporting, filters, export)

Analytics are stored in a custom database table created on activation.

#### What is tracked
The plugin records events into the `togglix_vsfw_events` table:

- `popup_open`
- `update_success`
- `update_failed`

Each event can also store:
- `product_id`, `variation_id`
- `user_id`
- `session_key` (Woo session customer id if available; otherwise IP+UA hash)
- `status` (e.g., `success`, `error`, `blocked`)
- `meta` (JSON; used for “reason” codes and other details)

#### Date range filter
- **Inputs**: `From` and `To` (calendar dates)
- **Behavior**:
  - Dates are interpreted in site timezone for the UI.
  - Stored events use GMT timestamps; the filter converts the selected dates to an inclusive GMT range.

#### Summary metrics (selected range)
- **Popup opens**
- **Successful updates**
- **Failed updates**
- **Conversion rate** = `successful updates ÷ popup opens`

#### Failed updates by reason
Shows counts grouped by the `meta.reason` code stored on failed updates.

Common reasons include:
- `rules` (blocked by Rules tab / per-product disable)
- `no_matching_variation`
- `not_purchasable`
- `out_of_stock`
- `cart_item_not_found`
- `add_to_cart_failed`

#### Daily activity chart
A compact bar chart (opens / success / failed per day) rendered on the admin page for the selected range.

#### Top products in range
Lists the top products by total tracked events in the selected date range.

#### Export CSV
Exports the raw events for the selected date range.

- **File format**: CSV (UTF‑8 BOM, Excel-friendly)
- **Columns**: `id,event_type,product_id,variation_id,user_id,session_key,status,created_at,meta`
- **Permissions**: `manage_woocommerce`
- **Security**: WordPress nonce check (`togglix_vsfw_export_csv`)

## Per-product options (variable products only)

Location:
- `Products → Edit product → Product data → General`

These options are stored as post meta on the variable product:

### Disable variation switcher
- **Meta key**: `_togglix_vsfw_disable` (`yes`/`no`)
- **Default**: `no`
- **What it does**:
  - Completely disables the Edit link and variation switching for this product, even if global settings allow it.

### Custom “Edit” link label
- **Meta key**: `_togglix_vsfw_edit_label` (string)
- **Default**: empty (falls back to global `edit_link_label`)
- **What it does**:
  - Overrides the Edit link label for this product only (both classic and Blocks output).
  - Example uses: “Change size”, “Change color”, “Edit options”.

## How switching works (technical behavior, for support)

### Cart-line accuracy
When the same variable product appears multiple times in the cart:

- The plugin targets the correct line item using WooCommerce’s **cart item key**:
  - Classic templates: passed via `data-cart-item-key` on the Edit link.
  - WooCommerce Blocks: taken from `args.cartItem.key`.

### Preserving quantity and custom cart data
When switching:

- Quantity is preserved from the original cart line.
- The plugin also attempts to preserve **custom cart item data** added by other plugins (by passing through non-core keys to `add_to_cart()`).

### Partial refresh vs full reload
After a successful update:

- If `use_partial_refresh` is enabled, the plugin tries to replace common cart/checkout containers via AJAX.
- If selectors cannot be replaced or an error occurs, it falls back to a full reload.
- Safe mode disables partial refresh.

## Compatibility notes (Marketplace-ready)

### WooCommerce Blocks vs classic templates

- **Blocks mode (recommended)**: Uses WooCommerce Blocks checkout/cart filters (`registerCheckoutFilters`) to inject the Edit link on block-based experiences.
- **Classic mode**: Uses the `woocommerce_cart_item_name` filter to append an Edit link in classic templates.

The **Compatibility profile** and **Blocks integration** toggle decide which path is active.

### HPOS (High-Performance Order Storage)

The plugin declares compatibility with WooCommerce **custom order tables (HPOS)** using `FeaturesUtil::declare_compatibility( 'custom_order_tables', … )`.

## Troubleshooting (recommended support content)

### The Edit link does not show
Check:
- General → **Enable plugin** is on
- Compatibility → **Enable on Cart** / **Enable on Checkout**
- Rules tab restrictions (role, include/exclude, coupon applied)
- Per-product: **Disable variation switcher** is not enabled
- Compatibility → Try **Safe mode** or set profile to **Classic-first**

### Switching fails with an error
Use:
- Compatibility tab → **Diagnostics → Copy report to clipboard**
- Analytics tab → check **Failed updates by reason** and export CSV if needed.

### Out-of-stock combinations appear selectable
Check:
- Behavior → **Inventory-aware switching** is enabled
Note:
- Some stores allow backorders. If backorders are allowed, a variation may be selectable even if not in stock.

## Option reference table (complete)

### Global option keys (`togglix_vsfw_settings`)

- `enable_plugin`
- `update_button_label`
- `edit_link_label`
- `popup_width`
- `primary_color`
- `show_variation_preview`
- `show_close_button`
- `close_on_overlay`
- `auto_reload_delay`
- `enforce_inventory_rules`
- `compatibility_profile` (`auto|classic|blocks|safe`)
- `enable_on_cart`
- `enable_on_checkout`
- `use_partial_refresh`
- `safe_mode`
- `enable_blocks_integration`
- `disable_when_coupon_applied`
- `allowed_user_roles` (array)
- `include_product_ids` (array)
- `exclude_product_ids` (array)
- `include_category_ids` (array)
- `exclude_category_ids` (array)
- `include_tag_ids` (array)
- `exclude_tag_ids` (array)

### Per-product meta keys (variable products)

- `_togglix_vsfw_disable` (`yes|no`)
- `_togglix_vsfw_edit_label` (string)

