Private content
Since private content is specific to individual users, it’s reasonable to handle it on the client (i.e., web browser).
Use our customer-data JS library to store private data in local storage, invalidate private data using customizable rules, and synchronize data with the backend.
This example shows a customer’s name on a cacheable page.
Create a section source
The section source class is responsible for retrieving data for the section. As a best practice, we recommend you put your code under the Vendor/ModuleName/CustomerData
namespace. Your classes must implement the Magento\Customer\CustomerData\SectionSourceInterface
interface.
The public method getSectionData
must return an array with data for private block.
Add the following to your component’s dependency injection configuration (di.xml
):
1
2
3
4
5
6
7
<type name="Magento\Customer\CustomerData\SectionPoolInterface">
<arguments>
<argument name="sectionSourceMap" xsi:type="array">
<item name="custom-name" xsi:type="string">Vendor\ModuleName\CustomerData\ClassName</item>
</argument>
</arguments>
</type>
Create a block and template
To render private content, create a block and a template to display user-agnostic data; this data is replaced with user-specific data by the UI component.
Do not use the $_isScopePrivate
property in your blocks. This property is obsolete and won’t work properly.
Replace private data in blocks with placeholders (using Knockout syntax). The init scope on the root element is data-bind="scope: 'compareProducts'"
, where you define the scope name (compareProducts
in this example) in your layout.
Initialize the component as follows:
1
2
3
<script type="text/x-magento-init">
{"<css-selector>": {"Magento_Ui/js/core/app": <?php echo $block->getJsLayout();?>}}
</script>
Configure a UI component
The UI component renders block data on the Magento storefront. To initialize the UI component, you must call the initialization method _super()
.
All properties are available in the template.
Example of defining a UI component in a layout
Invalidate private content
Specify actions that trigger cache invalidation for private content blocks in a sections.xml
configuration file in the Vendor/ModuleName/etc/frontend
directory. Magento invalidates the cache on a POST or PUT request.
The following example adds comments to app/code/Magento/Catalog/etc/frontend/sections.xml to show you what the code is doing.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?xml version="1.0"?>
<!--
/**
* Copyright © 2016 Magento. All rights reserved.
* See COPYING.txt for license details.
*/
-->
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Customer:etc/sections.xsd">
<!-- invalidates the "compare-products" section when a user
adds a product to the comparison, resulting in a "catalog/product_compare/add" POST request -->
<action name="catalog/product_compare/add">
<section name="compare-products"/>
</action>
<!-- invalidates the section when a customer removes a product from the comparison -->
<action name="catalog/product_compare/remove">
<section name="compare-products"/>
</action>
<!-- invalidates the section when a customer clears all products from the comparison -->
<action name="catalog/product_compare/clear">
<section name="compare-products"/>
</action>
</config>
Use only HTTP POST or PUT methods to change state (e.g., adding to a shopping cart, adding to a wishlist, etc.) and don’t expect to see caching on these methods. Using GET or HEAD methods might trigger caching and prevent updates to private content. For more information about caching, see RFC-2616 section 13
Other examples:
Version private content
Private content, which is stored in the browser local storage, uses the private_content_version
cookie to store the version.
Versioning works as follows:
- The user performs some action, such as adding to a cart, that results in an POST or PUT request to the Magento application.
- The server generates the
private_content_version
cookie for this user and returns the response to the browser. - JavaScript interprets the presence of the
private_content_version
cookie to mean that private content is present on the page, so it sends an AJAX request to the Magento server to get the current private content. -
The server’s reply is cached in the browser’s local storage.
Subsequent requests with the same data version are retrieved from local storage.
- Any future HTTP POST or PUT request changes the value of
private_content_version
and results in the updated content being cached by the browser.
Cacheable page checklist
-
Pages use GET requests
-
Pages render only cacheable blocks
-
Pages render without sensitive private data; session and customer DTO objects are empty
-
Functionality specific to both current session (customer) and page should be written using JavaScript (e.g., related product listing should exclude items that are already in the shopping cart)
-
Model and block level should identify themselves for invalidation support
-
Declare a custom context variable if you plan to show different public content with the same URL
Non-cacheable page checklist
-
Use POST requests to modify Magento state (e.g., adding to shopping cart, wishlist, etc.)
-
Blocks that can’t be cached should be marked as non-cacheable in the layout. However, be aware that adding a non-cacheable block to a page prevents the full page cache from caching that page.
-
Controllers that don’t use layouts should set
no-cache
HTTP headers