I want to add a CSS class to the body
when the customer is logged in or not. I thought this would work:
<body>
<customer_logged_in>
<attribute name="class" value="customer-logged-in"/>
</customer_logged_in>
<customer_logged_out>
<attribute name="class" value="customer-logged-out"/>
</customer_logged_out>
But that doesn't seem to work. Is there any way to do this via the layout?
Best Answer
This can be easily done by hooking into the page renderer. After all, that's the class responsible for rendering the
<body>
-tag.It always starts easy...
If you look at
\Magento\Framework\View\Result\Page::render()
, you'll see that the argumentbodyAttributes
is build like this:Magento\Framework\View\Page\Config\Renderer::renderElementAttributes()
is a public method which we can hook into:etc/frontend/di.xml
:And
Renderer.php
:Now, this should do the trick.
Well, as long as you're not using full page cache...
Full Page Cache and customer sessions
Full Page cache has a very interesting way of working that you should be aware of. That is: if all elements in the page qualify for caching, the customer session is 'depersonalized'. This is done to make sure that no customer details accidentally end up in the cached pages. After all, caching is your best friend and your worst enemeny.
The method responsible for this is
Magento\PageCache\Model\DepersonalizeChecker::checkIfDepersonalize()
.What this means for us, is that whenever a page is qualified for full page caching, our customer session is depersonalized. So we can no longer check
$this->customerSession->isLoggedIn()
to determine whether or not to add the class to the body.To fix this you have to write a plugin for the depersonalizer as well:
di.xml
:DepersonalizeChecker.php
:BEWARE OF WHAT YOU ARE DOING HERE! Because basically you are disabling full-page cache entirely for every logged in customer. So if you are going to mess with the outcome of the depersonalizer, you'd be best of by adding some extra additions:
In conclusion
The combination of the two plugins should get you going into implementing this feature. It's funny how a simple task like 'adding a class to the body if condition x == y' can introduce a lot more complexity than - for example - adding a new shipping carrier or something.
It's just important that you know what you're doing.