Dynamic Topmenu with Full Page Caching in Magento

blockscachefull-page-cachelayoutmagento-enterprise

I've spent way too many hours digging through SO and the rest of the net looking for a solution to this, and after trying just about every suggestion I'm still at a loss.

The issue is we need dynamic content in the top bar. Currently this looks like…
Home | Categories | <LoggedInBlock> <LoggedOutBlock> <EveryoneBlock>
…where the three blocks are Static Blocks editable in the admin, and the LoggedIn and LoggedOut blocks are added in the layout via <customer_logged_in/out>.

Ultimately the goal is simply to have top menu links editable in the admin, and certain links hidden if logged in or out (whereas some links always appear). This works fine until Full Page Caching is enabled, at which point either the logged in version or logged out version get cached for all users to see regardless of their status.

Most recommendations revolve around block values like cache_lifetime/cache_tags/etc, but messing with any of these at the layout or block level seems irrelevant in regards to the Full Page Cache. The Catalognavigation FPC container isn't comparing cache ids and does it's job before the layout loads. I can only imagine Enterprise_PageCache_Model_Container_Catalognavigation needs to be overwritten to have user status somehow worked into it, but I can't say I know how to mess with these crazy caching functions.

I've considered giving up on hole punching the top menu althg and just removing the default one entirely, setting up a simple core/template block to build the menu in. Only issue with this is the categories menu in the Topmenu_Renderer block is intricately weaved into the topmenu code, to the point that trying to separate it seems impossible on the already expired time budget.

Magento EE 1.14.1

Best Answer

If you remove them entirely from the layout doing something like below in the default tags in your local.xml

<reference name="header">
  <action method="unsetChild"><name>top.links</name></action>
</reference>

or per page like

<remove name="top.links" />

Then create a mini module with one controller method such as

public function indexAction()
{   
    $this->loadLayout();
  $this->renderLayout();
}

add this to your local.xml

<dynamicblocks_index_index>

    <reference name="root">
        <action method="setTemplate"><template>dynamicblocks/index.phtml</template></action>
    </reference>   


</dynamicblocks_index_index>

then in your dynamicblocks/index.phtml

<?php echo $this->getLayout()->getBlock('top.links')->toHtml() ?>

This whole page should just render your toplinks and by loading it from the website through an ajax call it won't get cached.