Search by

actualizer / price-hide

actualizer

Hide prices and cart access for non-logged-in users and specific customer groups

Package info

github.com/actualizer/ActPriceHide

Type:shopware-platform-plugin

pkg:composer/actualizer/price-hide

Statistics

Installs: 10

Dependents: 0

Suggesters: 0

Stars: 1

Open Issues: 0

1.3.1 2026-09-12 21:50 UTC

This package is auto-updated.

Last update: 2026-09-12 21:51:33 UTC


README

A Shopware 6 plugin that provides advanced price visibility control and purchase-funnel access management. Hide prices and close cart and checkout for non-logged-in users or specific customer groups.

Features

  • Hide prices for non-logged-in users
  • Close cart, cart mutation and checkout for non-logged-in users
  • Customer group-based price visibility control
  • Information bar display when prices are hidden
  • Server-side lockout of every cart and checkout route, including /checkout/cart.json and order placement
  • AJAX and normal page request compatibility
  • Multi-language support (German & English)
  • Compatible with Shopware 6.7.1+

Price-Leak Protection

When prices are hidden, the plugin actively closes every known leak vector so that numeric prices never reach an unauthorised visitor, search engine, or scraper. All of these respect the existing customer-group allowlist: a logged-in customer in an allowed group still sees every price in every channel.

Server-side (introduced in v1.1.x–v1.2.0):

  • data-product-information attribute on product cards — the price key is omitted entirely from the JSON blob that Shopware core emits on every card (listing, category, search, CMS sliders, cross-selling, suggest, wishlist). The key is removed rather than zeroed — a zero would be indexed as "0 EUR" in search results.
  • Listing price-range aggregation — the price aggregation is stripped from listing/search/suggest Criteria, so min/max values do not appear in XHR responses or filter sliders.
  • JSON-LD schema.org/Offer on the product detail page — the page_product_detail_json_ld_script block is suppressed, so no structured-data price reaches search engines or scrapers.
  • Server-rendered inline tracking scriptsgtag('event', 'view_item', {…}) and dataLayer.push({…}) blocks rendered by tracker plugins (GA4, Google Ads, Meta Pixel via GTM, WbmTagManagerEcomm, etc.) are scanned at response time; price, value, item_price, revenue keys are removed from item objects, and outer value / revenue totals in the enclosing call are stripped as well.

Client-side (introduced in v1.2.0):

  • window.dataLayer.push wrapper — inline <script> at the top of <head> intercepts every subsequent push and applies the same strip rules. Covers interaction-triggered events (add-to-wishlist, quick-view, scroll-triggered view_item_list) that server-side filters cannot see because the payload is built in the browser at interaction time.
  • JS-plugin fallback — a second install channel registered on <body> reads the config from <meta> tags and installs the wrapper on DOMContentLoaded. Kicks in when a customer theme overrides layout/meta.html.twig without calling {{ parent() }} and suppresses the primary inline script.

Operations (v1.2.2)

  • Kill-switch: ActPriceHide.config.priceLeakGuardEnabled (default on). Toggles the client-side dataLayer guard — the server-side HTML filters always stay active. Toggle in admin + cache clear, no redeploy.
  • CLI verification:
    bin/console act:price-hide:verify-guard [--url=https://shop.example]
    Fetches the storefront and returns exit code 0 (inline primary channel active), 1 (fallback channel only — theme probably overrides layout_head_meta_tags_charset without parent()), or 2 (no guard detected at all). Suitable for deploy pipelines.
  • Admin guard-status card: the plugin config page shows the current protection state directly below the info banner — green (primary channel), yellow (fallback only), red (not installed). Re-check button re-runs the probe.

Purchase funnel (v1.3.0)

Cart markup renders from the line-item and summary templates, which emit their own price output and share no block with the product templates this plugin overrides. Hiding the cart button removes the entry point, not the route. Every route under frontend.checkout. and frontend.cart. is therefore closed server-side while prices are hidden — matching by prefix so routes added by future Shopware versions are covered by default:

Route group Response while prices are hidden
Landing pages: cart.page, confirm.page, finish.page, register.page 302 to /account/login
XHR fragments: frontend.cart.offcanvas, frontend.checkout.info 204, empty body
Everything else: cart.json, cart mutation, POST /checkout/order, … 403, empty body

/checkout/cart.json returned the full cart as JSON including unitPrice, totalPrice and positionPrice, bypassing every HTML filter. Cart mutation and order placement were reachable as well, so a customer outside the allowed groups could complete an order without ever seeing a price. Both were closed in v1.3.0.

The two widget routes are answered empty rather than redirected because their callers inject the response into the offcanvas or the header container. The redirect is 302, never 301 — the destination depends on plugin configuration and login state. It carries no redirectTo: the core hands a logged-in customer straight back to that route, which for a customer outside the allowed groups bounced between cart and login until the browser gave up (fixed in v1.2.10).

This replaces the <meta http-equiv="refresh"> used up to v1.2.7, which shipped the fully priced cart page and only then asked the browser to leave.

Further leak vectors closed in v1.2.8

  • Footer VAT notice — the showVatNotice render parameter is set to false, so the core footer drops its VAT/shipping line while prices are hidden.
  • OpenGraph product priceproduct:price:amount and product:price:currency are dropped on the product detail page. The override now defers to the core block via {{ parent() }} whenever prices are visible; up to v1.2.7 it replaced the block unconditionally with a stale copy that also lost ogTitle, ogDescription, openGraphMedia and og:video.

Requirements

  • Shopware 6.7.1 or higher
  • PHP 8.4 or higher

Installation

Via Composer (recommended)

composer require actualizer/price-hide
bin/console plugin:refresh
bin/console plugin:install --activate ActPriceHide
bin/console cache:clear

Manual

  1. Download or clone this plugin into your custom/plugins/ directory
  2. Install and activate the plugin via CLI:
    bin/console plugin:refresh
    bin/console plugin:install --activate ActPriceHide
    bin/console cache:clear

Configuration

  1. Go to Admin Panel → Settings → System → Plugins
  2. Find "Actualize: Price Hide" and click on the three dots
  3. Click "Config" to access plugin settings
  4. Configure customer groups that should see prices
  5. Set up redirect behavior and display options

How it works

  1. Price Visibility Check: The plugin checks if the current user is logged in and belongs to an allowed customer group
  2. Price Hiding: If conditions are not met, prices are hidden across all storefront pages (product listings, detail pages, cart, etc.)
  3. Funnel Access Control: Every route under frontend.checkout. and frontend.cart. is answered with a redirect, an empty fragment or 403 before the rendered response leaves the server
  4. Information Display: Shows informational messages to users when prices are hidden

Technical Details

Architecture

  • Global Template Variables: Uses Shopware's native template variable system for reliable data access
  • HidePriceResolver: Single source of truth for the hide decision, shared by the render subscriber, listing-criteria subscriber, inline-tracking filter, dataLayer-guard subscriber, and cart-route guard.

Events Used

  • StorefrontRenderEvent - To inject price hiding logic into all storefront pages
  • KernelEvents::RESPONSE (priority 0) - Purchase-funnel guard. Runs on the response rather than the request because the SalesChannelContext is only resolved on kernel.controller
  • KernelEvents::RESPONSE (priority -128 / -127) - Post-rendering HTML filters for data-product-information attributes and inline tracking scripts
  • Template overrides for price-sensitive areas

Template Extensions

The plugin extends multiple templates to ensure consistent price hiding:

  • Product listing pages
  • Product detail pages
  • Search suggestions
  • Header cart button and widget
  • layout/meta.html.twig for the head-level dataLayer-guard inline script

AJAX Compatibility

All template files support both AJAX and normal page requests through dual checking logic:

  • Request attributes for AJAX requests
  • Page extensions for normal page loads

Translations

The plugin includes translations for:

  • German (de-DE): Preis verstecken
  • English (en-GB): Price hide

Translation keys:

  • header.priceHideInfoNotLoggedIn
  • header.priceHideInfoNotAllowed
  • header.priceHideInfoAriaLabel (accessibility)

Development

Building/Testing

After making changes to templates or translations:

bin/console cache:clear
bin/console theme:compile

If the client-side dataLayer guard is touched, rebuild the storefront and admin bundles:

./bin/build-storefront.sh
./bin/build-administration.sh

Debugging

The plugin respects Shopware's logging configuration. Check your log files for any price hiding logic errors.

Compatibility

  • Shopware Version: 6.7.1+
  • PHP Version: 8.4+
  • AJAX Support: Full compatibility with AJAX requests

Support

For issues and feature requests, please use the GitHub issue tracker.

License

This plugin is licensed under the MIT License - see the LICENSE file for details.

Credits

Developed by Actualize

Made with ❤️ for the Shopware Community