Skip to main content
Estimated Upgrade Time: 15 to 45 minutes depending on how much you customized auth models and event listeners.

Updating Dependencies

You should update the following dependencies in your application’s composer.json file: shopper/framework to ^2.6 shopper/stripe to ^2.6 (If installed) Then run:
composer update -W
After updating, run the migrations:
php artisan migrate
v2.6 ships one new package: shopper/cart. The tax system is built into shopper/core. Both are included in shopper/framework and installed automatically. Their migrations run with the standard php artisan migrate command.

High Impact Changes

Auth Models and Traits Moved from Core to Admin

Likelihood of Impact: High Affects applications that import Role, Permission, ShopperUser, or HasProfilePhoto directly. The Role and Permission models, the ShopperUser and HasProfilePhoto traits, and the spatie/laravel-permission dependency have all moved from shopper/core to shopper/admin. If you import any of these directly in your application code, update the namespaces:
Before (v2.5)After (v2.6)
Shopper\Core\Models\RoleShopper\Models\Role
Shopper\Core\Models\PermissionShopper\Models\Permission
Shopper\Core\Models\Contracts\ShopperUserShopper\Models\Contracts\ShopperUser
Shopper\Core\Traits\ShopperUserShopper\Traits\InteractsWithShopper
Shopper\Core\Models\Traits\HasProfilePhotoShopper\Traits\HasProfilePhoto
The old namespaces are still present in shopper/core as deprecated aliases and will continue to work until v3.0, but you should migrate at your earliest convenience. The role configuration has also moved. If you referenced the admin role from config/shopper/core.php, update to config/shopper/admin.php:

Before (v2.5)

config('shopper.core.roles.admin')

After (v2.6)

config('shopper.admin.roles.admin')

Medium Impact Changes

New Migrations

v2.6 adds 15 new migrations across two packages. Run php artisan migrate after updating. Tax system (shopper/core):
MigrationDescription
2026_02_24_000001_create_tax_providers_tableTax provider registry
2026_02_24_000002_create_tax_zones_tableGeographic tax zones
2026_02_24_000003_create_tax_rates_tableRates and override rules
2026_02_25_000001_add_tax_amount_to_orders_tabletax_amount column on orders
2026_02_25_000002_add_tax_columns_to_order_items_tabletax_amount and tax_rate_id on order items
2026_02_25_000003_create_order_tax_lines_tableTax line snapshots
2026_02_25_000004_add_allow_backorder_to_products_tableallow_backorder column on products
2026_02_25_000005_make_user_id_nullable_on_inventory_histories_tableuser_id becomes nullable
Cart package (shopper/cart):
MigrationDescription
2026_03_01_000001_create_carts_tableCart model
2026_03_01_000002_create_cart_lines_tableCart line items
2026_03_01_000003_create_cart_addresses_tableBilling and shipping addresses
2026_03_01_000004_create_cart_line_adjustments_tableDiscount adjustments per line
2026_03_01_000005_create_cart_line_tax_lines_tableTax lines per cart line
Performance (shopper/admin):
MigrationDescription
2026_02_26_000001_add_status_indexes_to_orders_tableIndexes on order status columns

Order and Product Event Renaming

Likelihood of Impact: Medium Affects applications with listeners registered for OrderCancel or AddNoteToOrder events. Two events have been renamed for consistency. If you registered listeners for either of these events, update your EventServiceProvider:
Before (v2.5)After (v2.6)
Shopper\Core\Events\Orders\OrderCancelShopper\Core\Events\Orders\OrderCancelled
Shopper\Core\Events\Orders\AddNoteToOrderShopper\Core\Events\Orders\OrderNoteAdded

Before (v2.5)

use Shopper\Core\Events\Orders\OrderCancel;
use Shopper\Core\Events\Orders\AddNoteToOrder;

protected $listen = [
    OrderCancel::class => [CancelOrderHandler::class],
    AddNoteToOrder::class => [NotifyTeam::class],
];

After (v2.6)

use Shopper\Core\Events\Orders\OrderCancelled;
use Shopper\Core\Events\Orders\OrderNoteAdded;

protected $listen = [
    OrderCancelled::class => [CancelOrderHandler::class],
    OrderNoteAdded::class => [NotifyTeam::class],
];

Render Hooks: Enum Replaced by Scoped Classes

Likelihood of Impact: Medium Affects applications that registered render hooks using the RenderHook enum in v2.5. The RenderHook enum (Shopper\Enum\RenderHook) from v2.5 had 6 layout-level hooks. It has been replaced by seven scoped classes organized by business domain. If you used any of these hooks, update to LayoutRenderHook:
Before (v2.5)After (v2.6)
RenderHook::HeadStartLayoutRenderHook::HEAD_START
RenderHook::HeadEndLayoutRenderHook::HEAD_END
RenderHook::BodyStartLayoutRenderHook::BODY_START
RenderHook::BodyEndLayoutRenderHook::BODY_END
RenderHook::ContentStartLayoutRenderHook::CONTENT_START
RenderHook::ContentEndLayoutRenderHook::CONTENT_END
The new classes are in the Shopper\View namespace. See the Render Hooks documentation for the complete list of available hooks across all 7 scoped classes.

Before (v2.5)

use Shopper\Enum\RenderHook;

Shopper::renderHook(RenderHook::HeadEnd, fn () => '...');

After (v2.6)

use Shopper\View\LayoutRenderHook;

Shopper::renderHook(LayoutRenderHook::HEAD_END, fn () => '...');

Low Impact Changes

allow_backorder Column Added to Products

A new boolean column allow_backorder has been added to the products table. It defaults to false. No action is required — the migration handles it automatically. When allow_backorder is true on a product or variant, the cart’s add() and update() methods skip the stock availability check entirely, allowing the item to be added regardless of inventory level.

user_id Nullable on Inventory Histories

The user_id foreign key on the inventory_histories table is now nullable. This accommodates stock changes triggered by automated processes rather than an admin action. No action is required.

System Permissions Cleanup

Three system permissions have been removed from the seeder and are no longer created on fresh installations:
Removed permissionReason
manage_mailNo longer used by any component
impersonateNo longer used by any component
setting_analyticsNo longer used by any component
For existing installations these permissions remain in your database but have no effect. You can delete them manually if you want to keep your permissions table clean:
use Shopper\Models\Permission;

Permission::query()->whereIn('name', ['manage_mail', 'impersonate', 'setting_analytics'])->delete();

Server-Side Authorization Enforced Across Admin Components

Likelihood of Impact: Medium Affects applications with custom roles beyond the default administrator role. All admin Livewire pages and slide-overs now enforce permissions server-side via $this->authorize(). Previously, many components relied only on sidebar visibility to restrict access — a direct URL or Livewire call was enough to bypass the check. The following table lists every area that is now protected and the permission required:
AreaPermission
Settings pages (General, Carriers, Payment Methods, Taxes, Tax Zones, Legal)access_setting
Tax rate overrides slide-overaccess_setting
Shipping zone and rate slide-oversaccess_setting
Team management pages and slide-oversview_users
Product attributes slide-overedit_attributes
Product pricing slide-overedit_products
Choose product attributes slide-overedit_products
Related products slide-overedit_products
Generate variants slide-overedit_product_variants
Update variant slide-overedit_product_variants
Collection products and rules slide-oversedit_collections
Re-order categories slide-overedit_categories
Create shipping label slide-overedit_orders
Reviews index page and detail slide-overbrowse_reviews
Tags index pagebrowse_tags
The administrator role is not affected as it holds all permissions by default. For custom roles, assign the relevant permissions before upgrading:
use Spatie\Permission\Models\Role;

$role = Role::findByName('manager');

$role->givePermissionTo([
    'access_setting',
    'view_users',
    'edit_attributes',
    'edit_products',
    'edit_product_variants',
    'edit_collections',
    'edit_categories',
    'edit_orders',
    'browse_reviews',
    'browse_tags',
]);
Review all custom roles in your installation and assign the permissions appropriate to their scope before upgrading. Users with insufficient permissions will receive a 403 response.

Shopper Enums Now Implement Shopper\Core\Contracts

Shopper’s internal enums (OrderStatus, ProductType, etc.) now implement HasLabel, HasIcon, HasColor, and HasDescription from Shopper\Core\Contracts instead of Filament\Support\Contracts. This removes the Filament dependency from shopper/core and keeps the core package framework-agnostic. This has no impact on your application. Since Shopper runs on top of Filament, your own custom enums can continue to implement either Filament\Support\Contracts or Shopper\Core\Contracts — the method signatures are identical.

New Features

Cart Package

shopper/cart is now bundled with Shopper. It provides a full cart management system with pipeline-based calculation, discount validation, tax integration, and order conversion. See the Cart documentation for setup and usage.

Tax System

A built-in tax system is now available. Configure tax zones per country (or country + province), assign rates, and define override rules for specific products, product types, or categories. Taxes are calculated automatically in the cart pipeline. See the Taxes documentation for full details.

Dashboard Analytics

The dashboard now includes five new Livewire components: a 12-month revenue bar chart, stat cards with month-over-month trends, a recent orders table, a top-selling products table, and an interactive setup guide. All data is cached with stale-while-revalidate semantics. See the Dashboard documentation.

Abandoned Carts

A new admin page at Orders → Abandoned Carts lists carts that have been inactive for longer than the configured threshold (default: 60 minutes). The threshold is configurable in config/shopper/cart.php:
'abandoned_after_minutes' => 60,

Addon System

Shopper now has a first-class addon API for packaging extensions. An addon can register routes, Livewire components, sidebar entries, views, settings items, and permissions as a single unit. See the Addons documentation.

Render Hooks

62 named render hooks are now available across all admin pages. Use them to inject content into specific positions without modifying any Shopper views. See the Render Hooks documentation.

Migration Checklist

1

Update dependencies

Run composer update -W after updating shopper/framework to ^2.6.
2

Run migrations

Run php artisan migrate to apply all 15 new migrations.
3

Update auth model namespaces

Replace Shopper\Core\Models\RoleShopper\Models\Role and Shopper\Core\Models\PermissionShopper\Models\Permission wherever you import them.
4

Update auth trait namespaces

Replace Shopper\Core\Traits\ShopperUserShopper\Traits\InteractsWithShopper and Shopper\Core\Models\Traits\HasProfilePhotoShopper\Traits\HasProfilePhoto.
5

Update renamed events

Replace OrderCancelOrderCancelled and AddNoteToOrderOrderNoteAdded in your event listeners.
6

Update render hooks

Replace the old RenderHook enum constants with the new scoped class constants if you used render hooks in v2.5.
7

Update role config key

Replace config('shopper.core.users.admin_role') with config('shopper.admin.roles.admin') if you referenced it directly.
8

Review custom role permissions

Assign access_setting, view_users, edit_attributes, edit_products, edit_product_variants, edit_collections, edit_categories, edit_orders, browse_reviews, and browse_tags to any custom role that should access the corresponding areas. Optionally delete the unused manage_mail, impersonate, and setting_analytics permissions from your database.