= 1.21.8 =
* Add a clearly named Hidden Input directly to the expanded General Fields palette.
* Keep hidden inputs compatible with Page title, URL parameter, Custom field/meta, and Referrer page URL prefilling.

= 1.21.7 =
* Keep mapped request fields editable when the request page is opened directly without a valid source context or when the configured prefill resolves to an empty value.
* Preserve manually entered car names and prices during server-side submission verification when no trusted request parameters were supplied.

= 1.21.6 =
* Remove the automatic visible Regarding/request-context field and add a defensive legacy-markup hide while retaining signed hidden verification data.
* Improve native dropdown arrow spacing in RTL and LTR forms and restore the WordPress admin menu icon selector.

= 1.21.5 =
* Add a Referrer page URL prefill source for hidden or visible attribution fields.
* Simplify the form-builder prefill list to Page title, URL parameter, Custom field/meta, and Referrer page URL.
* Remove the automatic visible Regarding/request-context field; map the page title into a chosen form field when it should be displayed.

= 1.21.4 =
* Support any published, publicly queryable WordPress post type when resolving signed request-form context, including dealership themes that use `listing`.
* Add a safe same-site `[string_request_url]` shortcode that builds cash or test-drive CTA links from the current post ID without hardcoding or exposing trusted title and price values in the URL.

= 1.21.3 =
* Add per-field request prefill mapping in the form builder for source-post title, ID, type, custom meta, request type, and sanitized URL query parameters.
* Let mapped text-like fields render read-only while re-resolving trusted source-post values during submission so browser changes cannot replace the server value.
* Suppress the automatic title context box when the form already maps the verified source title into a selected field.

= 1.21.2 =
* Resolve a published car, product, or doctor from validated request-page links using the existing `type` and `id` parameters instead of trusting the title supplied in the URL.
* Render the verified source title as a localized read-only form input and bind the allowlisted cash/drive request type to the signed submission context.

= 1.21.1 =
* Add safe Solid / Gradient submit-button backgrounds with two colors, a configurable angle, and an optional validated theme custom property with a fallback color.
* Apply the configured button background consistently in the builder preview and frontend hover, focus, and disabled states while preserving existing width, text color, and icon settings.
* Capture signed page, WooCommerce product, doctor, and car context for request forms; verify it server-side, resolve a current String Product ID when possible, and preserve the WordPress title in Submission attributes.

= 1.21.0 =
* Add opt-in WooCommerce coupon definition synchronization through the authenticated External Partner API.
* Bind each WordPress site UUID to its authenticated tenant/store before coupon writes, preventing cross-store identity collisions.
* Add resumable paginated backfill, lifecycle create/update/trash/delete queueing, bounded retries, rate-limit handling, and daily reconciliation.
* Preserve percent, fixed-cart, and fixed-product semantics plus WooCommerce restrictions without transmitting raw restricted customer emails.

= 1.20.23 =
* Display independent WooCommerce commerce labels for active, cleared, abandoned, and ordered journeys.
* Stop cart lifecycle changes from overwriting the linked Submission CRM pipeline status; WooCommerce order-status mapping remains unchanged.

= 1.20.22 =
* Let the first due WooCommerce event batch run immediately instead of holding it behind an empty-queue synchronization lock.
* Preserve asynchronous batch delivery; storefront requests still do not wait for String when no event is ready.

= 1.20.21 =
* Record each synchronized WooCommerce cart action as its own String Submission note so it appears as a separate Activity Log entry.
* Mark individual cart actions synchronized only after String accepts their corresponding note, so acknowledged activities are not resent on normal retries.

= 1.20.20 =
* Populate the String Source selector when changing an existing mapping to WooCommerce Orders / Submissions, including immediately after a successful source refresh.

= 1.20.19 =
* Store and advance WooCommerce cart journeys locally when commerce event tracking is enabled, without requiring a String cart-to-Submission mapping.
* Keep remote String Submission creation and status synchronization optional and mapping-dependent.

= 1.20.18 =
* Keep WooCommerce event tracking disabled until an administrator explicitly enables it, and honor the WordPress statistics-consent API when available.
* Support environment-managed API credentials so the client secret does not need to be stored in WordPress options.
* Strip query strings and fragments from page/referrer URLs before transmission, rate-limit public event endpoints, and reject invalid identity capture.
* Restrict raw commerce events and their customer PII to users with the manage-all-leads capability.
* Cap failed event delivery retries and retain terminal failures for administrator diagnosis.

= 1.20.17 =
* Queue authoritative WooCommerce cart abandonment, payment failure, purchase, order status, cancellation, and refund events.
* Keep retries idempotent with deterministic SHA-256 message IDs and link server events to the existing String client and Submission.
* Carry the checkout browser ID onto authoritative order events so first-touch and last-touch attribution stay connected without adding browser ad pixels.

= 1.20.16 =
* Add cart viewed, cart updated, checkout started, and payment info entered storefront events.
* Send cart contents, value, currency, stable cart journey ID, and the existing String Submission ID when available.
* Deduplicate repeated server hooks inside the same request while preserving each queued event's stable retry message ID.

= 1.20.15 =
* Send WooCommerce commerce batches with the canonical `woocommerce` provider and customer key.
* Capture page URL, path, referrer, canonical UTM campaign fields, user agent, and available Meta/TikTok/Snap/Google/Microsoft click identifiers on storefront events.
* Reuse existing merchant ad cookies when present without injecting a second browser pixel.

= 1.20.14 =
* Restore Events as a visible The String CRM admin tab and sidebar item.
* Add a dedicated Events page backed by the existing WooCommerce storefront event log, event filters, sync filters, and pagination.
* Keep Customers as the unified CRM record area; Events is a raw commerce activity view, not a return of the old Entries model.

= 1.20.13 =
* Added an explicit Refresh String sources action to WooCommerce Orders / Submissions mapping.
* Empty/stale Source catalog cache is retried directly against String before showing an empty selector.
* Source API errors now show the actual response and explicitly identify the required sources.read scope for 403 responses.
* Preserves a previously saved source ID if the remote catalog is temporarily unavailable.

= 1.20.12 =
* Fix logged-in carts still missing on WooCommerce AJAX/Store API flows after 1.20.11.
* Capture immediately from WooCommerce's server-side woocommerce_ajax_added_to_cart checkpoint instead of relying on browser events.
* Add a shutdown repair checkpoint that creates only a missing non-empty logged-in cart journey from the final Woo cart state, including stale cleared/recovered journey rotation.
* Keep existing active/pending journeys untouched at shutdown to avoid duplicate Submissions or status regressions.

= 1.20.11 =
* Fix logged-in shoppers not creating an Active cart Submission until checkout on themes/custom AJAX flows.
* Reconcile the current cart immediately after classic WooCommerce and Woo Blocks add/remove events, while retaining the normal PHP hooks as the primary path.
* Add a late frontend fallback for non-empty logged-in carts; unchanged snapshots reuse the same cart journey and never create a duplicate Submission.

= 1.20.10 =
* Fix Customer profiles opened by a String client id showing empty local history after Fresh Sync.
* Hydrate the profile from carts, orders and commerce events linked to the same String client.
* Match carts/orders by remote client id as well as phone/email/customer id.

= 1.20.9 =
* Customers: added Fresh Sync reconciliation for missing String client links.
* Uses String Submission ownership when available, otherwise resolves phone-first then email.
* Backfills local carts, orders, browser identities and product events with the resolved String Client ID.

= 1.20.8 =
* Fix Customers page admin CSS/JS loading after menu restructure.
* Persist the owning String client ID on every synchronized WooCommerce cart and order.
* Backfill historical Customer rows from their existing String Submission IDs so records already visible in String no longer appear as Local identity.
* Replace the ambiguous Local identity label with Not linked only when no String client can actually be resolved.
* Promote recovered String client IDs into Customer profiles so Submissions and Appointments load against the correct String client.

= 1.20.6 =
* Customers replaces Entries as the primary customer-record area.
* Merged form submissions into customer identity grouping by normalized phone/email.
* Customer profiles now show local form submissions together with String/Woo commerce submissions.
* Customer list exposes Submission, Order, Cart, Product activity, and last-activity counts in one place.
* Old Entries bookmarks resolve to Customers for backward compatibility.

= 1.20.5 =
* Redesigned WooCommerce Customer Profile to match the String CRM customer-record layout with a unified header, KPI strip, and record tabs.
* Added Overview, Submissions, Orders, Carts, and Appointments tabs so each customer record category is separated and easy to scan.
* Submissions tab deduplicates the same String Submission when a cart later becomes an order, while preserving the Cart → Order journey link.
* Carts tab now keeps every cart journey, including carts that later produced an order, with cart status, linked order, String Submission, total, and activity time.
* Orders tab lists all WooCommerce orders with Woo status, stored String status, String Submission, products, total, and created time.
* Appointments tab loads the customer's String appointment history through the External Partner API when appointments.read is available, with short caching to protect rate limits.
* Overview combines product behaviour, bought-together insights, unified customer timeline, contact identity, and lifetime commerce KPIs.

= 1.20.4 =
* Customer Orders & Carts now shows every cart that has not yet become a real WooCommerce order, regardless of cart status.
* Abandoned, cleared, expired, failed-payment, pending and active cart journeys remain visible with their actual status.
* Once a WooCommerce order exists for the journey, only the order row is shown to prevent duplication.
* Customer KPI renamed from Active carts to Carts without order.

= 1.20.3 =
* Simplified Customer profile around a single Product activity list.
* Product badges now follow the latest cart/order lifecycle: Added to cart, Active/Abandoned cart, or the real WooCommerce order status. View-only products intentionally have no status badge.
* Replaced separate Most viewed/Purchased panels with one product journey view plus Bought together.
* Customer Orders view now combines all WooCommerce orders with active carts that do not yet have an order.
* Paid deal size now uses payment evidence (date_paid/completed/refunded) instead of treating Processing alone as purchased.

= 1.20.2 =
* Add WooCommerce Customers tab with one customer profile aggregating Product Events, cart activity, checkout identification, payment activity, and order events into a single time-ordered timeline.
* Preserve anonymous context in the timeline: product events that happened before checkout identification are labelled Anonymous even after they are stitched to the known customer.
* Add customer Orders tab showing Woo status, String Submission ID, and the String status recorded by the last successful sync.
* Add customer commerce insights: total deal size (net of refunds), most-viewed products with Purchased badges, purchased-product history, and products bought together in the same successful order.
* Persist the String status ID/name accepted during Woo order sync so customer order history can display String-side state without extra live API calls.

= 1.20.1 =
* WooCommerce identity resolution is now phone-first: when checkout phone and email match different String clients, the same cart/order Submission belongs to the phone client instead of failing.
* Cart and order Submission Additional Data now sends primary/secondary phone and email roles for the current commerce journey; this does not auto-merge client contact records.
* Progressive checkout keeps one Submission: an email-first Submission can move to the phone owner when the phone is captured later.
* No automatic client merge is performed when phone and email belong to different clients.

= 1.20.0 =
* Smart phone fallback: a high-confidence Egyptian local mobile number such as 010/011/012/015 is normalized with +20 even when the checkout/address country is different; customer country is never overwritten by phone country.
* Identity resilience: a valid email can create/sync the String client even when the supplied phone fails String phone/country formatting validation. Phone uniqueness conflicts are never bypassed.
* Keeps explicit international (+ / 00 / calling-code) normalization global and unchanged.

= 1.19.9 =
* Add long-lived first-party Browser ID identity stitching: 180-day rolling known-identity retention, 2-hour activity sessions, and a 24-hour anonymous-event lookback.
* Keep browser identity, activity session, and cart journey independent so cleared/completed carts never force browsing identity loss.
* Resolve the same normalized phone/email to the same String client across different devices while preserving separate browser IDs and separate cart Submissions.
* Store browser identity associations in a dedicated WordPress table; browser cookies contain pseudonymous IDs only.
* Stop carrying an older phone/email forward when a newly observed identifier differs; already-identified historical events are not reassigned.
* Add Browser ID and String Client ID to commerce event storage/payloads and clarify them in WooCommerce Product Events admin.

= 1.19.8 =
* Fix Product Events browser-session fragmentation for anonymous WooCommerce visitors.
* Product browsing now uses a stable first-party 30-minute browser session instead of the cart journey key.
* When a guest later supplies email/phone, all waiting events from that browser session are stitched to the identity and queued.
* Remember identified guest details for subsequent product events in the same Woo session.
* Keep the current cart key as an upgrade bridge for anonymous events created by older plugin versions.

= 1.19.7 =
* Track checkout payment attempts separately from cart activity: Pending/in-progress, explicit payment failure, success/recovery, cancellation, and pre-payment checkout validation errors.
* Use WooCommerce's checkout_order_processed moment as the payment-attempt marker, then classify frontend checkout_error as Payment failed only when the order actually reached gateway processing.
* Gateway failures that leave the Woo order in Pending payment (for example a missing/invalid payment-gateway token) now keep Woo untouched but mark the same cart journey Failed and move the same String Submission to the mapped WooCommerce Failed status.
* Persist payment state/error/gateway/order information into String Additional Data and keep the exact payment activity/error in the Woo cart activity log.
* Prevent background Pending-order sync and checkout field refreshes from reopening a failed payment; a real retry changes the same Submission back to Pending payment.
* WooCommerce Entries now shows Payment failed / Payment in progress independently from the raw Woo order status, so Pending Woo orders with a failed gateway attempt are no longer misleading.

= 1.19.6 =
* Smart WooCommerce phone normalization: accepts +E.164, 00-prefixed, international-without-plus, and national/local numbers.
* Normalizes Arabic/Persian numerals and ignores trailing phone extensions.
* Local numbers use Woo billing/account country and fall back to the WooCommerce store base country.
* Customer country is no longer inferred from the phone dialing code; phone country and customer country remain independent per String PR #6808.

= 1.19.5 =
* Fix phone-only cart/customer sync when checkout has not supplied a billing country yet.
* Infer an ISO country from an unambiguous international WooCommerce calling code (for example +966 → SA), then resolve that ISO against String countries.
* Keep ambiguous shared calling codes such as +1 blocked unless WooCommerce provides billing_country, avoiding unsafe customer matching.
* Preserve all 1.19.4 cart-journey and live product-sync behavior.

= 1.19.4 =
* Cart journey semantics: clearing the cart now closes the current cart Submission instead of keeping it open for same-session reactivation.
* The cleared Submission keeps its full history, is moved to the configured Cleared cart status, and its product snapshot is emptied.
* Any later add starts a fresh cart journey and fresh String Submission even when the shopper is still logged in and still in the same WooCommerce session.
* Cart journey keys now include a per-journey nonce so rotating a cleared/recovered cart cannot recreate the same key.
* Upgrade-safe handling prevents carts cleared under 1.18.8–1.19.3 from being reactivated accidentally after upgrade.

= 1.19.3 =
* Fix live WooCommerce cart product synchronization: Active/Cleared/Abandoned cart PATCHes now send the exact current String product/category relation set, not only product names in Additional Data.
* Adding, removing, quantity-changing or clearing cart items updates the same String Submission product snapshot; no duplicate Submission is created.

= 1.19.2 =
* Fix WooCommerce Entries fatal error caused by refund objects being returned in the order query.
* Restrict the commerce Orders table to shop orders and defensively skip WC_Order_Refund / HPOS OrderRefund records.
* Preserve all v1.19.1 source-mapping and update-safe behavior.

= 1.19.1 =
* WooCommerce Orders / Submissions now has an explicit String Source mapping dropdown instead of forcing a source named WordPress.
* The selected source is used consistently for both cart and order Submissions across the same commerce journey.
* Existing mappings preselect WordPress when available for an easier upgrade, but the saved source selection is authoritative.

= 1.19.0 =
* Add a local WooCommerce Product Events stream modelled after Salla customer product events: product search, list viewed/filtered/sorted, viewed, clicked, shared, reviewed, added to cart, and removed from cart.
* Logged-in customers are identified immediately; anonymous guest events are retained by WooCommerce session and enriched/queued when the cart later captures email or phone.
* Add The String CRM > Entries > WooCommerce > Product Events with event/customer/product/session/sync visibility.
* Batch identified events through the existing External Partner connection to the new backend contract POST /api/v1/external/ecommerce/events; if the backend is not deployed yet, events remain local as Waiting backend and retry safely.
* Add a backend handoff document listing the four new universal event keys String still needs: product_list_filtered, product_list_sorted, product_shared, product_reviewed.
* Keep WhatsApp timing, eligibility, suppression, and reminder actions entirely in String Automations.

= 1.18.8 =
* Keep Cleared cart inside the same WooCommerce session and the same String Submission; clearing the cart no longer rotates the cart journey key.
* Adding a product again after Cleared cart reactivates the existing Submission as Active cart and restarts the inactivity timer.
* Record an explicit Cart reactivated activity note in String while retaining the exact product-added activity.
* Preserve one cart journey across add/remove/quantity/clear/reactivate activity until checkout is recovered or the WooCommerce session genuinely changes.

= 1.18.7 =
* Create Active cart immediately on the first product add for logged-in WooCommerce customers by falling back to the account email/name when billing data is not yet present.
* Track cart activity for both logged-in and guest customers: product added, product removed, quantity changed, and cart cleared. Anonymous guest activity is retained locally and synced once email/phone identifies the cart.
* Append unsynced cart activity to the same String Submission as notes and keep last cart action/change in Submission attributes.
* Record Cleared cart locally as a terminal journey, optionally map it to a dedicated String status, stop abandonment for that journey, and rotate the cart key so a later add starts a fresh Submission.
* Show Cleared carts and recent cart activity under The String CRM > Entries > WooCommerce > Carts.
* Reduce unnecessary cart status writes: ordinary add/remove activity updates the Submission without re-sending Active cart status on every change.

= 1.18.6 =
* Make plugin updates/reinstalls non-destructive: preserve String connection, Content Sync mappings, queue/backfill state, site UUID and scheduled sync work.
* Remove automatic cross-copy deactivation during activation; a duplicate copy now exits without touching the active installation.
* Keep the deactivation hook non-destructive so WordPress file replacement cannot interrupt synchronization.
* Keep uninstall non-destructive until an explicit confirmed data-removal action is added.

= 1.18.5 =
* Set the String source of newly created WooCommerce cart/order Submissions to WordPress automatically.
* Added WooCommerce Orders and Carts views under The String CRM > Entries.
* Show customer identity, cart/payment status, remote Submission ID, source, synchronization state, last sync/error and timestamps without duplicating WooCommerce order storage.

= 1.18.4 =
* Use the normal WooCommerce Pending payment mapping after checkout starts while keeping the cart abandonment timer active.
* Keep one Submission across Active cart -> Pending payment -> Abandoned cart / Failed payment -> Processing/Completed.
* Preserve explicit WooCommerce Failed as its own failed cart state so the timeout does not later overwrite it with Abandoned cart.
* Restart the timeout only on a real retry into Pending, not on repeated background order-save hooks.
* Keep all recovery messaging and timing in String Automations.

= 1.18.3 =
* Fixed a checkout race that could create two String Submissions for one cart/order journey.
* The existing cart Submission ID is now written to the Woo order before woocommerce_new_order live sync runs.

== Changelog ==

= 1.18.2 =
* Fixed the cart-to-order lifecycle for Pending payment orders. WooCommerce can create an order before checkout/payment is complete; that no longer marks the cart recovered.
* A linked Pending payment order keeps the same String Submission in Active cart, then moves to Abandoned cart after the configured inactivity timeout.
* Pending order re-sync respects the local cart state, so an Abandoned cart is not reset back to the generic Pending payment String status.
* Added an `order_id` link to the local cart table and a one-time 1.18.1 repair for carts incorrectly marked recovered by Pending payment orders.
* Added a throttled request fallback alongside the one-minute WP-Cron scan for more reliable status transitions.
* Clarified the Content Sync UI: Active/Abandoned are String statuses, not new WooCommerce order statuses.


= 1.18.1 =
* Cart journey: create/update the String Submission immediately once checkout has a usable email or phone.
* Added configurable Active Cart and Abandoned Cart String status mappings.
* Default abandonment window is now 10 minutes; the scan runs every minute for a closer transition.
* Abandonment changes only the Submission status. WhatsApp and all follow-up actions remain in String Automations.
* Recovered WooCommerce orders keep the same Submission ID and continue through the existing order/status sync.

= 1.18.0 =
* Add WooCommerce abandoned-cart capture with a configurable inactivity window.
* Keep anonymous carts local until email or phone is available, then create one String Submission for the abandoned cart.
* When checkout converts the cart into an order, reuse the same String Submission so the cart and order remain one CRM journey.
* Store cart/recovery state in a plugin-owned table and scan due carts every five minutes with WP-Cron.

= 1.17.16 =
* Harden database queries for WordPress.org security scanning and use prepared identifier placeholders.
* Fix non-literal translation calls for WordPress internationalization compatibility.

= 1.17.15 =
* Fixes HPOS/admin live-order auto sync when an early incomplete save fails before billing identity or line items are complete.
* Live order fingerprints now include billing email/phone/country/address and line-item identity, quantity and totals.
* Failed foreground sync attempts are no longer memoized, so later hooks in the same request retry immediately instead of waiting for cron/manual Sync Now.
* Phone-only guest orders can recognize unambiguous international numbers entered without a leading plus sign (for example 962...).
* Queues/backfill remain fallback/repair paths; successful live saves still deduplicate repeated hooks in the same request.

= 1.17.14 =
* Make WooCommerce new/update order hooks perform an immediate String sync instead of only queueing work.
* Make HPOS `woocommerce_after_order_object_save` and `woocommerce_order_object_updated_props` use the immediate order-sync path.
* Keep the persistent queue, Action Scheduler/WP-Cron, shutdown processor, and retry hooks as fallbacks only when the immediate String request fails or is rate-limited.
* Preserve one String Client per matched email/phone while keeping each WooCommerce order isolated by its own order-specific Submission ID/integration ID.
* Queue one repair backfill after upgrade so orders missed by older queue-only live hooks are reconciled automatically.

= 1.17.13 =
* Fix WooCommerce order notes that some admin/REST flows report as `system`; String now syncs them instead of silently discarding them.
* Verify notes returned by the String Submission API and append only note lines that are actually missing, preventing both false-success and duplicate note snapshots.
* Add direct REST/comment note hooks plus one-time reconciliation so note auto-sync does not depend on the normal order-save lifecycle.

= 1.17.12 =
* Sync WooCommerce customer/manual order notes to the linked String Submission on create and later note changes.
* Listen to order-note add/delete hooks so note synchronization is automatic and does not depend on Sync Now.
* Ignore WooCommerce-generated system notes and preserve 1.17.11 live order/customer/product synchronization behavior.

= 1.17.11 =
* Orders / Submissions no longer fail just because a WooCommerce product needs a String currency lookup.
* Existing String products are resolved before currency lookup and are attached with their WooCommerce sub-category using a minimal product update that does not require currency.
* A product/category dependency failure no longer blocks the base Submission, status, price, or WooCommerce Additional Data; the plugin records a warning and retries the product attachment automatically.
* Added direct final-save synchronization for WooCommerce orders, products, and customers while retaining the persistent queue as a retry/fallback path.
* Added a one-shot repair backfill for existing Orders / Submissions mappings.

= 1.17.10 =
* Resolve WooCommerce order currency by exact String currency-code search with forced-cache fallback.
* Make order status re-sync idempotent when the Submission already has the mapped status.
* Queue one repair backfill after upgrade so previously blocked WooCommerce orders retry automatically.

= 1.17.9 =
* Orders -> Submissions no longer requires a Products mapping. Each Woo order line item resolves its own product_cat hierarchy automatically, creates/reuses the String parent Category and Sub-category, creates/reuses the String Product, then sends category_ids + product_ids with the Submission.
* Woo top-level-only product categories are safely placed under one stable WooCommerce Products parent because String products require a sub-category.

= 1.17.8 =
* Fix upgrade packaging so WordPress replaces the existing plugin directory instead of installing a duplicate copy.
* Fix internal plugin version/duplicate-activation guard to match the installed release.
* Fix WooCommerce Order -> Submission product attachment so line-item products are always resolved and attached automatically.
* Force on-demand product sync to bypass bulk catalog filters for products that were actually purchased.
* Persist WooCommerce status -> String status IDs locally and add a cross-request creation lock to prevent duplicate status creation during live order sync.
* Make the configured Lead Journey mapping authoritative for order status resolution; fallback defaults are only used when no Lead Journey mapping exists.
* Queue a one-time order reconciliation after upgrade.

= 1.17.5 =
* Live WooCommerce sync no longer depends on Action Scheduler/WP-Cron: final order/product/customer saves are processed at request shutdown with persistent retry queues as fallback.
* Added HPOS/admin/REST order save hooks and one-time reconciliation for orders missed by older versions.

= 1.17.4 =
* Make WooCommerce live sync truly automatic: new/updated orders, customers, products, and mapped services are queued through WooCommerce Action Scheduler with WP-Cron fallback; no manual **Sync Now** is required.
* Add checkout-complete order hooks for classic and Store API checkout flows.
* Apply order products before the final String status transition, then use the dedicated Submission status endpoint so Stage/Status history is updated reliably.
* Treat an order line item as strong sync intent: an enabled Product mapping is applied on demand even when normal catalog filters would exclude that purchased product.
* Retry transient/non-rate-limit order dependency failures automatically instead of silently dropping the queued order.
* Auto-create/reuse the WooCommerce Orders Stage/status mapping on demand when Orders sync is enabled without a separate Lead Journey card.
* One-time upgrade repair re-syncs existing WooCommerce orders and turns product attachment on for previously created Orders mappings.

= 1.17.3 =
* Prevent fatal redeclaration errors when an older duplicate The String CRM installation is still present or active.
* Automatically deactivates duplicate active copies while keeping the current plugin installation active.

= 1.17.2 =
* Fix WooCommerce Order → Submission linkage when the order is synchronized before catalog/workflow backfills finish.
* Resolve/create the mapped String status on demand for the current WooCommerce order status.
* Resolve/synchronize mapped WooCommerce products on demand and attach their String product IDs to the Submission.
* Queue one dependency-ordered repair backfill on upgrade from earlier versions so existing synced orders receive their missing status/products.


= 1.17.1 =
* Packaging fix: keep the existing plugin directory so WordPress upgrades/replaces the active plugin instead of installing a duplicate copy.
* Includes all WooCommerce customer/order sync functionality from 1.17.0.

= 1.17.0 =
* Add **Customers / Contacts** Content Sync for registered WooCommerce customers. Customers are matched to existing String clients by email/phone before a new Contact is created.
* Add **Orders / Submissions** Content Sync with a required String Branch and no dependency on a separate customer mapping.
* Every WooCommerce order automatically resolves or creates its related String client from billing email/phone, including guest-checkout orders.
* Group multiple WooCommerce orders for the same email/phone under the same String client/Lead while keeping one separate Submission per order.
* Stop conflicting orders safely when the email and phone point to different String clients.
* Map WooCommerce order status to the String status created by the Lead Journey mapping, attach already-synced String Products when available, and send the order total as the Submission manual price.
* Persist the remote String Submission ID on the WooCommerce order so repeat syncs update the same Submission rather than creating another one.
* Add rate-limited background queues for future WooCommerce order/customer changes and rate-limited backfill for existing customers/orders.

= 1.16.0 =
* Add **Lead Journey — Stages / Statuses** as a Content Sync mapping entity for WooCommerce order statuses.
* Create or reuse one String Stage by bilingual name, then create/update enabled WooCommerce statuses under it.
* Let administrators map each WooCommerce status to an English/Arabic String status name and an explicit String status type.
* Give every synchronized status a stable WordPress/WooCommerce `integration_id` so repeat syncs update instead of duplicating.
* Process workflow synchronization through the same adaptive partner rate-limit batching used by large catalog backfills.
* Require `workflow.read` / `workflow.write` for this mapping; WooCommerce Orders → String Submissions remains intentionally deferred to the next step.

= 1.15.2 =
* Sync taxonomy-backed Categories from the complete WordPress taxonomy catalog, including terms with zero assigned posts/products.
* Keep new/edited empty taxonomy terms synchronized automatically while respecting the partner API rate limit.

= 1.15.1 =
* Fix category taxonomy sync so multiple assigned WordPress/WooCommerce terms are created as separate String sub-categories instead of a single comma-separated child name.
* Keep the existing simple mapping UI: fixed parent + taxonomy child is supported without extra hierarchy controls.
* Store all resolved remote category IDs locally while preserving one deterministic primary category for String Product compatibility.


= 1.15.0 =
* Large Content Sync jobs are split automatically into API-safe batches using the Business Partner `rate_limit_per_minute` returned by String.
* Each sync window uses only 70% of the configured partner request limit, leaving headroom for normal site/API activity.
* Backfills track the real number of String API requests made, pause before exhausting the safe budget, and resume automatically in the next one-minute window.
* HTTP 429 remains a fallback safety path: the current item is preserved and retried after `Retry-After` instead of being marked failed.
* Future post/product create and update events now enter the same shared rate-limited queue instead of making immediate API calls, so bulk imports cannot create request bursts.
* Dependency mappings are processed in order (Categories/Sub-categories before Services and Products), and large 1k+ catalogs remain resumable across cron runs.

= 1.14.9 =
* Added optional per-mapping WordPress filters so only matching posts/products are synchronized to String.
* Filters support custom fields and taxonomies with equals, contains, one-of, empty/non-empty, and inverse operators.
* Taxonomy filter values use visible term names and show selectable existing terms.
* Backfill now reports filtered-out items as skipped instead of failed, and future create/update sync respects the same filters.


= 1.14.8 =
* Reduce External Partner API usage during Content Sync to avoid unnecessary 429 rate limits.
* Category-only mapper pages no longer fetch unrelated Products, Services, Currencies, Brands, Branches, or Users catalogs.
* Cache remote catalog collections briefly and reuse them across backfill batches.
* Category hierarchy sync reuses cached parent/child rows, avoids redundant refetches, and only PATCHes a category when its mapped data actually changed.
* Existing 429 pause/resume behavior remains enabled; rate-limited items are paused rather than counted as failed.

= 1.14.7 =
* Category hierarchy mappings now dereference WordPress term/post IDs and structured relationship values to their visible names before creating String categories.
* Field discovery shows relationship samples as ID → resolved name where possible, and taxonomy sources are clearly labeled as term-name mappings.
* Backfill is rate-limit aware: HTTP 429 pauses and resumes automatically instead of counting queued items as permanent failures.
* Future create/update sync retries automatically after partner API rate limits.

= 1.14.6 =
* Added Categories / Sub-categories as a first-class Content Sync mapping target.
* Map a WordPress field/taxonomy such as Make to the String parent Category and another such as Model to the String Sub-category.
* Category mappings create or update the required String parent/child hierarchy with stable integration IDs and reuse matching existing String categories when possible.
* Product Sub-category mapping can now choose “Use synced sub-category from Category mapping”; the plugin resolves/creates the dependency before creating or updating the Product.
* Existing published items are included in the same automatic backfill, and future WordPress creates/updates continue to sync automatically.
* Added preflight validation for missing/same Parent Category and Sub-category values and for missing Category mapping dependencies.

= 1.14.5 =
* Content Sync mapper now discovers WordPress taxonomies in addition to post meta/ACF keys.
* Mapping dropdowns show sample values from published content so fields such as make, category, and model are easier to identify.
* Catalog mappings can resolve String categories, brands, currencies, services, and relations from WordPress taxonomy terms.
* Required mapping preflight now reports the actual WordPress source value that failed to match a String catalog value.

= 1.14.4 =
* Show the exact per-post Content Sync backfill failures directly on the Content Sync screen.
* Improve Product/Service catalog mapping when WordPress/ACF fields store taxonomy term or post IDs: resolve the WordPress object name/slug first, then match it to the String catalog; only use a numeric value as a String ID when that ID actually exists.
* Clarify catalog mapping labels to support String ID, name, or code matching.

= 1.14.2 =
* Rebuilt Content Sync as a compact two-column field mapper: String Product/Service fields on the left and WordPress fields/custom keys on the right.
* String entity is selected first; only Product or Service fields for the active target are submitted.
* Selecting a WordPress post type now fetches its available custom-field/meta keys automatically, including ACF field definitions when available.
* Preserves all existing Product/Service sync behavior, multilingual resolution, existing mapping settings, backfill, and future create/update synchronization.
* WooCommerce-specific source fields are shown only when a WooCommerce Product post type is selected.

= 1.14.1 =
* Added multilingual-aware Product/Service Content Sync for WPML, Polylang, and TranslatePress.
* Normal title/content mappings now resolve English and Arabic translations automatically when available.
* Single-language sites safely mirror the available Product/Service name into both `name.en` and `name.ar`; descriptions use the same fallback unless a language is explicitly set to Do not sync.
* Explicit English/Arabic custom-field and static mappings keep highest priority over automatic multilingual discovery.
* WPML/Polylang translation siblings now share one stable Content Sync `integration_id`, preventing translated posts from creating duplicate String Products/Services.
* Added extension filters so other multilingual plugins can provide translation IDs/values without replacing the sync engine.

= 1.14.0 =
* Expanded Content Sync to cover every field currently accepted by the String External Partner Product and Service create/update APIs.
* Product mapping now includes bilingual name/description, price, SKU, quantity, category, currency, brand, address/location, phone/WhatsApp/email, status, working hours, Google Map URL, Product URL, branches, users, related services, and related products.
* Service mapping now includes bilingual name/description, price, parent service, expiry, insurance, reminders, upsell, instructions, Service URL, related services/products/users, plus prepared advanced duration/share-button mappings.
* Added WordPress featured-image, attached-media, WooCommerce main-image/gallery, and custom-media-reference mapping. Media URLs are prepared in the payload; actual remote attachment requires corresponding String External Partner API media support.
* Enabling Content Sync now automatically queues a complete backfill of all existing published mapped content; future published creates/updates continue syncing automatically.
* Added a visible backfill progress summary and safe full re-sync action.
* Expanded Content Sync catalog loading to Categories, Currencies, Brands, Branches, Users, Services, and Products.
* Fixed duplicate catalog API loading on the Content Sync settings screen and improved cleanup of background sync state on deactivation/uninstall.

= 1.13.4 =
* Renamed the public plugin branding from String Form to The String CRM.
* Kept the existing `string-form` plugin folder, text domain, shortcodes, database keys, and internal identifiers for backward compatibility.

= 1.13.3 =
* Fixed custom builder fields not being persisted in String Additional Data.
* Unmapped WordPress fields are now sent under `attribute[...]`; native String fields and explicitly mapped String Field Keys remain top-level.
* Preserved UTM attribution in the dedicated `utm[...]` payload and merged click IDs/integration provenance without overwriting custom attributes.
* Additional phone fields now reliably remain Additional Data unless explicitly mapped to a native String field.

= 1.13.2 =
* Fixed fatal errors/memory exhaustion when submitting forms with file uploads.
* File-bearing String submissions now stream attachments from disk instead of loading binary files into PHP memory.
* Multiple File Upload fields are merged into one attachments collection without changing their String upload contract.
* Added graceful transport errors when PHP cURL is unavailable instead of crashing the form submission.

= 1.13.1 =
* Appointment Branch/Product/Services controls now follow the public form language and direction.
* Appointment Services use a multi-select dropdown instead of inline checkboxes.
* Appointment options support editable English and Arabic public labels while preserving String IDs.


= 1.13.0 =
* Added configurable Appointment context for Branch, Product, and Services.
* Branch/Product/Service can be preset and hidden or exposed as visitor choices.
* Appointment calendar now loads real String availability through a secure WordPress proxy.
* Appointment slot duration follows the selected String service duration(s).
* Added Services to the editor catalog and appointment relationship filtering.

= 1.12.9 =
* Added Dynamic / Static Data workflow for String Branch and Product fields.
* Select Branch/Product records from String, then generate locked-ID options for the form.
* Added independent English and Arabic labels for every generated Branch/Product option.
* Custom labels can be renamed without changing the String ID submitted for routing.


= 1.12.8 =
* Fixed Grid column drop targets so palette fields and existing fields can be dropped directly into a column.
* Restored pointer interaction inside Grid rows while preserving the normal non-interactive field preview behavior elsewhere.
* Added stronger drag-enter/drag-over handling and clearer active-column feedback.
* Simplified Grid column and 12-unit width-control borders for a cleaner editor appearance.

= 1.12.7 =
* Redesigned Grid columns with a lighter, cleaner editor treatment and editable 12-unit column widths.
* Fields can now be dragged directly from the field palette into a Grid column.
* Existing fields can be dragged into a Grid column, between Grid columns, or back into the normal form flow.
* Added clear per-column drop targets and preserved mobile single-column rendering.

= 1.12.6 =
* Standardized the String routing field label as Product.
* Replaced the placeholder layout marker with a functional Grid Layout component.
* Grid rows support 1, 2, or 3 columns on a 12-unit layout system with configurable column spans that always total 12.
* Fields can be assigned to a grid row and column from Advanced Options, with a live layout preview in the builder.
* Grid columns collapse to a single column on small screens.

= 1.12.5 =
* Fixed the tracking modal so actions from the inactive step stay hidden.
* Replaced generated iframe/embed code with a native `[string_form]` shortcode carrying selected tracking and routing values.
* Routing overrides from generated links/shortcodes now work independently of the general UTM forwarding toggle.
* Empty/default routing values, including department `0`, are no longer added to generated tracking output.

= 1.12.4 =
* Prepared the public package for WordPress.org review.
* Removed remote JavaScript and image dependencies so plugin UI/assets are served locally.
* Removed suppression of other plugins' WordPress admin notices.
* Added a complete external-service and privacy disclosure plus WordPress Privacy Policy Guide text.
* Removes saved String credentials and Content Sync settings on uninstall while retaining business records.
* Added a PHP 7.4-compatible fallback when mbstring is unavailable.

= 1.12.3 =
* Distribution cleanup and documentation normalization for the public plugin package.
* Internal UI identifiers were normalized without changing form behavior or saved data.

= 1.12.2 =
* Form Builder follows the current WordPress admin language.
* Arabic WordPress admin renders the builder UI in Arabic with RTL direction; English remains LTR.

= 1.12.1 =
* Enabled multiple Phone fields, each with independent country and validation settings.
* The canonical phone field remains the main String CRM phone; additional phone fields remain available as additional submission data.

= 1.12.0 =
* Added WordPress-to-String Content Sync with WordPress as the V1 source of truth.
* Map WordPress post types or WooCommerce Products to String Products or Services.
* Added stable integration identifiers and manual Sync Now reconciliation.

= 1.11.7 =
* Fixed the String Form WordPress menu icon outside String Form pages.

= 1.11.3 =
* Added browser and server-side duplicate-submission protection.

= 1.11.2 =
* Added Excel export and a full Submission Profile view.

= 1.11.0 =
* Added optional country-aware phone validation, country filtering, and leading-zero normalization.

== Upgrade Notice ==

= 1.14.6 =
Adds dependency-aware Category/Sub-category hierarchy synchronization before Products, so mappings such as Make → Parent Category and Model → Sub-category can create everything required by the String Product API automatically.

= 1.14.2 =
Replaces the complex section-based Content Sync screen with a direct String-field-to-WordPress-key mapper and automatic custom-field discovery. Existing mappings remain compatible.

= 1.14.1 =
Adds multilingual Product/Service resolution. WPML/Polylang/TranslatePress translations are used when available; single-language content is mirrored safely into both String name languages, and translated post siblings update one remote entity.

= 1.14.0 =
Expands Product/Service mapping and automatically backfills existing published mapped content when Content Sync is enabled. Product/Service media URLs can be mapped now; remote media attachment still requires String External Partner API media support.

= 1.13.4 =
Renames the plugin display branding to The String CRM while preserving existing forms, shortcodes, settings, and integrations.

= 1.12.8 =
Fixes direct Grid drag-and-drop and cleans up Grid width/border styling.

= 1.12.7 =
Improves the Grid editor and adds direct drag-and-drop field placement into columns.

= 1.12.6 =
Adds the functional 12-column Grid Layout builder and standardizes the String Product field label.

= 1.12.5 =
Fixes tracking-link/shortcode generation and modal step actions.

= 1.12.4 =
Recommended for WordPress.org distribution: removes remote static assets and documents String data processing and external-service usage.
