<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Adam Moss</title>
    <description>The personal blog of Adam Moss, including detailed Magento 1 &amp; 2 posts brought to you by the Magento Fox</description>
    <link>http://adammoss.co.uk/</link>
    <atom:link href="http://adammoss.co.uk/feed.xml" rel="self" type="application/rss+xml"/>
    <pubDate>Sun, 02 Sep 2018 12:26:48 +0000</pubDate>
    <lastBuildDate>Sun, 02 Sep 2018 12:26:48 +0000</lastBuildDate>
    <generator>Jekyll v3.7.3.1</generator>
    
      <item>
        <title>Connect TomTom Runner to Vitality Health</title>
        <description>&lt;p&gt;&lt;img src=&quot;/assets/posts/sync.png&quot; alt=&quot;Finished&quot; /&gt;&lt;/p&gt;

&lt;p&gt;As a precursor I should mention that the solution I’m describing in this post is for an Apple iPhone, however it could easily be done in a similar fashion on an Android with the equivalent of Apple Health.&lt;/p&gt;

&lt;p&gt;Choosing a sports/activity watch took a lot of research on my part. As someone who uses Nike+ and Strava to record runs and cycles I was adamant that my watch would send its data to those apps so I didn’t lose my historical data. The answer to this conundrum was a TomTom Runner 3 GPS watch, which has been great ever since I started wearing it.&lt;/p&gt;

&lt;p&gt;Then, earlier this year my private healthcare was switched to Vitality, a company that has a big emphasis on your day to day fitness via tracking, which all sounds great except that it’s long list of integrations doesn’t include TomTom! That’s right, your Garmin, FitBit, Apple Watch and Polar devices all connect except for TomTom.&lt;/p&gt;

&lt;p&gt;I asked TomTom and Vitality via Twitter if they had any intentions of creating a connection in the future and the answer was a resounding “no”. In order to get around this I realised that if I can get my data from TomTom Sports into Apple Health then Vitality can in turn get the data from Apple Health.&lt;/p&gt;

&lt;p&gt;I signed up to https://www.fitnesssyncer.com which allows you to create a source (TomTom Sports) and a destination (Apple Health) and bingo, the data is now moving across the apps and Vitality no longer thinks I sit on my arse all day (which I suppose I do a lot of anyway).&lt;/p&gt;

&lt;h2 id=&quot;how-to-do-it&quot;&gt;How to do it&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;First, make sure you’ve downloaded the TomTom Sports app to your phone and that your watch is correctly synced up.&lt;/li&gt;
  &lt;li&gt;Second, download the Vitality app (for iPhone &amp;amp; Android), go to Settings &amp;gt; Synce Apple Health Data and choose how much data to sync.&lt;/li&gt;
  &lt;li&gt;Third, create an account on https://www.fitnesssyncer.com, download the app and create a ‘Source’ from TomTom Sport and a ‘Destination’ to Apple Health&lt;/li&gt;
&lt;/ol&gt;
</description>
        <pubDate>Sun, 08 Apr 2018 13:00:00 +0000</pubDate>
        <link>http://adammoss.co.uk/blog/connect-your-tomtom-runner-to-vitality/</link>
        <guid isPermaLink="true">http://adammoss.co.uk/blog/connect-your-tomtom-runner-to-vitality/</guid>
        
        
        <category>blog</category>
        
      </item>
    
      <item>
        <title>3 Peaks 2017 - A Broken Resolve</title>
        <description>&lt;p&gt;As I write this I am 24 hours removed from my second acquaintance with the Great Britain 3 Peaks Challenge. Unlike last time when I finished with a feeling of exhaustion-laden achievement, today I look back with disappointment and regret.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/posts/ben-nevis.jpg&quot; alt=&quot;Ben Nevis&quot; /&gt;&lt;/p&gt;

&lt;p&gt;At this point there’s probably cause for a bit of backstory to understand how I arrived at this personal denouement, so let me set the scene. We had already completed mountain number 1, Ben Nevis in northern Scotland, and what a pleasure it was. Warm air filled the silent, Scottish outback as the evening sunlight delicately kissed the edges of the wild panorama. The descent was a sight to behold, the green and gold mountainside at its finest. The climb lasted about 4 hours and we were soon on our way south for the second leg of our journey… and it couldn’t have been more different.&lt;/p&gt;

&lt;p&gt;Scafell Pike’s climate was of the wetter variety, it was 4:30am and the clear blue skies had been replaced with a full coating of heavy, turbulent rain clouds. The hibernating sun gave way to an inexorable downpour, but regardless we started the climb.&lt;/p&gt;

&lt;p&gt;The climb was straightforward but rather miserable given the worsening conditions. As summit fever kicked in the winds that rattled through piles of rocks increased in hostility as the horizontal rain spattered my face and bare legs unabatingly. All 6 of us by this point were completely soaked, and from a personal perspective I was becoming increasingly cold - the rain had long since penetrated my thin, not-so impermeable jacket and I was shivering like a leaf on the last day of autumn. My longstanding concerns about my ‘wet clothes’ not being waterproof enough were realised under the mountain’s harshest jurisdiction.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;“All 6 of us by this point were completely soaked, and from a personal perspective I was becoming increasingly cold”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Shortly after reaching the top of England’s highest mountain and posing for a quick photo, owing to my eagerness to get out of the cold I started to lead the team down the mountain. I pursued what I thought was the only trail of cairns away from the summit as if they were breadcrumbs in a forest.&lt;/p&gt;

&lt;p&gt;As we descended, following cairn after cairn, I was experiencing a growing frustration that the other guys weren’t in as much of a rush to get down as I was. I thought “am I the only one desperate to get out of here?”. In my trembling, sleep-deprived state I was constantly turning around expecting everyone to be hot on my heels but in actuality they were rightly taking their time negotiating the slippery and treacherous aspects of the downward route. The welfare of my teammates should have been as much of a concern to me as my own, but I let my anger at the situation rule my head.&lt;/p&gt;

&lt;p&gt;About 15 minutes into the decent we were faced with the realisation that we had taken the wrong path when we discovered a rescue point (a random white box) that was not passed on the way up. I had somehow led us down a completely different path.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;“I had somehow led us down a completely different path.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We deliberated briefly, one possibility that we go back up and start again, another that we search for the nearest recognisable landmark, but hastened by the desire to exit the adverse weather as quickly as possible we opted to continue down the wrong path. The hope was that we’d ultimately end up rejoining the previous route at some point. Well that did not happen, and little did we know that we were about to embark upon a long journey of hapless trudging through what can only be described as no-man’s land.&lt;/p&gt;

&lt;p&gt;A relatively short period of time had passed when we reached something that somewhat resembled ground level as we recklessly tumbled down the wrong side of the mountain. It was mostly a course of steep, grassy verges and we adopted a network of gushing mountain tributaries as our guide down the slippery slopes. This eventually led to a stunning waterfall that brought us mercifully to the foot of the mountain, out of the extreme weather, but in the middle of nowhere. We were now totally lost.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;“I found my frustration with the situation was also accompanied by a worsening resentment towards the practice of mountain climbing.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Food sources were running low and fatigue was setting in for several of the lads. To top it off we had no way of communicating with the outside world due to the lack of phone signal. Our one saving grace was that team leader Nick’s phone was able to just about register our GPS location allowing us to plan a vague route back towards our van. This ended up being a significant development without which could have landed the team in a more serious situation.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/posts/map.jpg&quot; alt=&quot;Ben Nevis&quot; /&gt;&lt;/p&gt;

&lt;p&gt;We finally found our way back to the van after traipsing through 9 miles of valleys, plains, foothills, marshes and rivers in the non-stop rain. I found my frustration with the situation was also accompanied by a worsening resentment towards the practice of mountain climbing. I was pissed off, just like the others probably were, and from that point I had lost my desire to finish the challenge.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;“I’ve always persevered through adversity, but this time I let myself down…”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The challenge itself was technically dead in the water (pun intended) as we had no chance of making up what ended up being 5 hours of lost time, and all my clothes were soaked to the point of no rescue. I stuffed my sodden clothes &amp;amp; shoes into carrier bags and tied them up with no intention of reopening them until I got home. On top of this I was feeling worn out from the amount of shivering my body had devoted to fighting the cold that had settled in my bones. I decided to quit the 3 peaks challenge.&lt;/p&gt;

&lt;p&gt;Arriving at the point of quitting any physical challenge is not something I’ve ever done before, I’ve always persevered through adversity, but this time I let myself down.&lt;/p&gt;

&lt;p&gt;Several hours later upon arriving at Mt Snowdon I could have resurrected my wet clothes and coped with the cold fabric for one last push (important lesson - try to bring spare shoes) - this didn’t stop the other guys who simply geared back up and got on with it. Yes, I have already got a successful “3 Peaks Challenge” under my belt so it didn’t mean as much to me as some of the others, and I know that from a physical standpoint I wouldn’t have had any problems with another ascent, despite the extra-curricular events on Scafell Pike. My legs were tired but far from written-off.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;“I stuffed my sodden clothes &amp;amp; shoes into carrier bags and tied them up with no intention of reopening them until I got home”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In spite of all this however I sat in the van because I simply didn’t want to climb the last mountain. I let my emotions get in the way of my targets and my principles and for that I feel so so disappointed. I also want to apologise for not seeing it through with the rest of the guys, some of whom could have done with my co-operation and experience during the final trek. I send my congratulations to the others on completing the challenge, regardless of the timeframe it’s still a huge achievement (perhaps a bigger one due to the detour!).&lt;/p&gt;

&lt;p&gt;Later this year I face my second full marathon, a 13-mile Tough Mudder and my first 100-mile cycle event, which I now know will have very different outcomes. There will be no quitting, there will be no regrets. The important lesson I’ve learned this week is that you get out of these challenges what you put into them and for me this will always be remembered as my failure.&lt;/p&gt;
</description>
        <pubDate>Tue, 13 Jun 2017 09:00:00 +0000</pubDate>
        <link>http://adammoss.co.uk/blog/3-peaks-2017-a-broken-resolve/</link>
        <guid isPermaLink="true">http://adammoss.co.uk/blog/3-peaks-2017-a-broken-resolve/</guid>
        
        
        <category>blog</category>
        
      </item>
    
      <item>
        <title>Cookies, Full Page Cache and Private Data Tracking in Magento 2</title>
        <description>&lt;p&gt;Let me start by saying this: learning how to track private data in Magento 2 was a ballache. Now that’s out of my system I can continue with this post… Yes it was a ballache but it ended up being very easy. Here’s the situation:&lt;/p&gt;

&lt;p&gt;There are tons of JavaScript tracking scripts that get added to sites in order to send all kinds of data to their respective systems. They’re the Starbucks of the web, a new one seems to pop up every day. By the way, if you’re not using &lt;a href=&quot;https://www.google.co.uk/analytics/tag-manager/&quot;&gt;Google Tag Manager&lt;/a&gt; to do this then you’re insane.&lt;/p&gt;

&lt;p&gt;Well, in case you haven’t guessed this post is all about how to implement GTM tracking in Magento 2 without having your data carved into stone for all to see by Magento 2’s full page cache.&lt;/p&gt;

&lt;h3 id=&quot;the-problem&quot;&gt;The problem&lt;/h3&gt;

&lt;p&gt;I had a situation where I had to track a lot of customer data and therefore had to make this data available in the GTM Data Layer.&lt;/p&gt;

&lt;p&gt;To keep it simple I’ll just focus on how to track a newsletter subscriber’s email address when they use the basic newsletter form. This data is not posted back to any page on the website, and even if it was, the name could potentially get cached on the next loaded page meaning the next user could see my email address.&lt;/p&gt;

&lt;p&gt;As tracking code normally resides within the page HTML how do you get around this?&lt;/p&gt;

&lt;h3 id=&quot;local-storage&quot;&gt;Local storage?&lt;/h3&gt;

&lt;p&gt;One option could be to save the posted data in local storage and then access it via JS on the next page load (in the same fashion as the mini cart). It then turned out that local storage is basically the last thing loaded so my &lt;code class=&quot;highlighter-rouge&quot;&gt;datalayer.push()&lt;/code&gt; script had already ran twenty minutes prior with a null value.&lt;/p&gt;

&lt;h3 id=&quot;the-solution-use-cookies&quot;&gt;The solution… use cookies!&lt;/h3&gt;

&lt;p&gt;I looked at the way Magento had handled &lt;code class=&quot;highlighter-rouge&quot;&gt;datalayer.push()&lt;/code&gt; in their own &lt;code class=&quot;highlighter-rouge&quot;&gt;Magento_GoogleTagManager&lt;/code&gt; module and it seemed that the most sensible course of action would be to use cookies in the same way.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Intercept the data in an observer/plugin&lt;/li&gt;
  &lt;li&gt;Set data to a cookie in PHP&lt;/li&gt;
  &lt;li&gt;Retrieve data on frontend in JS&lt;/li&gt;
  &lt;li&gt;Delete cookie&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I have left out the majority of the basic module files for simplicity, but here’s the key bits:&lt;/p&gt;

&lt;h4 id=&quot;etcdixml&quot;&gt;/etc/di.xml&lt;/h4&gt;

&lt;p&gt;First I register a &lt;a href=&quot;/magentofox/magento-2-basics-part-6-using-plugins/&quot;&gt;plugin&lt;/a&gt; that will watch a function in the following class: &lt;strong&gt;Magento\Newsletter\Model\Subscriber&lt;/strong&gt;.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-xml&quot; data-lang=&quot;xml&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;config&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;xmlns:xsi=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;http://www.w3.org/2001/XMLSchema-instance&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;xsi:noNamespaceSchemaLocation=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;urn:magento:framework:ObjectManager/etc/config.xsd&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;type&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Magento\Newsletter\Model\Subscriber&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;plugin&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;trackSubscriber&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;type=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;MagentoFox\Track\Plugin\TrackSubscriber&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;sortOrder=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;1&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;disabled=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;false&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/type&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/config&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h4 id=&quot;plugintracksubscriberphp&quot;&gt;/Plugin/TrackSubscriber.php&lt;/h4&gt;

&lt;p&gt;I’m using a plugin to set a cookie after a customer has successfully subscribed to the newsletter. Once I have the information I need I use the &lt;code class=&quot;highlighter-rouge&quot;&gt;CookieManagerInterface&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;CookieMetadataFactory&lt;/code&gt; classes to set my cookie and I’m JSON encoding the result.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-php&quot; data-lang=&quot;php&quot;&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;namespace&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;MagentoFox\Track\Plugin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;TrackSubscriber&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;protected&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$cookieManager&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;protected&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$cookieMetadataFactory&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;protected&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$jsonHelper&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;__construct&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;\Magento\Framework\Stdlib\CookieManagerInterface&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$cookieManager&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;\Magento\Framework\Stdlib\Cookie\CookieMetadataFactory&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$cookieMetadataFactory&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;\Magento\Framework\Json\Helper\Data&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$jsonHelper&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;cookieManager&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$cookieManager&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;cookieMetadataFactory&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$cookieMetadataFactory&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;jsonHelper&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$jsonHelper&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;afterSubscribe&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;\Magento\Newsletter\Model\Subscriber&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$subscriber&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$subscriber&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getStatus&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;

            &lt;span class=&quot;nv&quot;&gt;$subscriberData&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$subscriber&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;

            &lt;span class=&quot;nv&quot;&gt;$publicCookieMetadata&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;cookieMetadataFactory&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;createPublicCookieMetadata&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
                &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;setDuration&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3600&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;setPath&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'/'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;setHttpOnly&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

            &lt;span class=&quot;nv&quot;&gt;$customerData&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
                &lt;span class=&quot;s1&quot;&gt;'Email'&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$subscriberData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'subscriber_email'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;

            &lt;span class=&quot;nv&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;cookieManager&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;setPublicCookie&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;customerData&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                &lt;span class=&quot;nv&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;jsonHelper&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;jsonEncode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$customerData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
                &lt;span class=&quot;nv&quot;&gt;$publicCookieMetadata&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h4 id=&quot;viewfrontendrequirejs-configjs&quot;&gt;/view/frontend/requirejs-config.js&lt;/h4&gt;

&lt;p&gt;I’m now declaring a new require class that will contain methods I use for handling cookies:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;config&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;s1&quot;&gt;'*'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;na&quot;&gt;MagentoFoxTrack&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;      &lt;span class=&quot;s1&quot;&gt;'MagentoFox_Track/js/cookies'&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h4 id=&quot;viewfrontendwebjstrackingjs&quot;&gt;/view/frontend/web/js/tracking.js&lt;/h4&gt;

&lt;p&gt;The reason for these functions will become clear in a moment.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;nx&quot;&gt;define&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([],&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;s2&quot;&gt;&quot;use strict&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;

            &lt;span class=&quot;na&quot;&gt;getCookie&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;){&lt;/span&gt;
                &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;cookie&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot; &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;cookie&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
                &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;search&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot; &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;=&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
                &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;setStr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
                &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;offset&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
                &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;end&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
                &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;cookie&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;length&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                    &lt;span class=&quot;nx&quot;&gt;offset&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;cookie&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;indexOf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;search&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
                    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;offset&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                        &lt;span class=&quot;nx&quot;&gt;offset&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;search&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
                        &lt;span class=&quot;nx&quot;&gt;end&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;cookie&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;indexOf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;offset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
                        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;end&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                            &lt;span class=&quot;nx&quot;&gt;end&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;cookie&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
                        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
                        &lt;span class=&quot;nx&quot;&gt;setStr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;decodeURI&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;cookie&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;substring&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;offset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
                    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
                &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
                &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;setStr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;

            &lt;span class=&quot;na&quot;&gt;delCookie&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;date&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Date&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
                &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;cookie&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;=&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;; path=/; expires=&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;date&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;toUTCString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
                &lt;span class=&quot;nb&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;cookie&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;cookie&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;

            &lt;span class=&quot;na&quot;&gt;parseJson&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;json&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;json&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;decodeURIComponent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;json&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;replace&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\+&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;/g&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;' '&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
                &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;JSON&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;parse&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;json&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h4 id=&quot;viewfrontendtemplatessubscriberphtml&quot;&gt;/view/frontend/templates/subscriber.phtml&lt;/h4&gt;

&lt;p&gt;This file is where the magic happens. First we initialise our new JS class &lt;code class=&quot;highlighter-rouge&quot;&gt;MagentoFoxTrack&lt;/code&gt; and we pass it as an argument with require. This allows our methods to be used wherever and whenever.&lt;/p&gt;

&lt;p&gt;We then grab our &lt;code class=&quot;highlighter-rouge&quot;&gt;customerData&lt;/code&gt; cookie, check that it is not null, parse the JSON which will turn it back into an object, and push to GTM. Finally we delete the cookie on the fly.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;script &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;type=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;text/x-magento-init&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;s2&quot;&gt;&quot;*&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;s2&quot;&gt;&quot;MagentoFoxTrack&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;
        &lt;span class=&quot;s1&quot;&gt;'MagentoFox_Track/js/cookies'&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;cookies&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;){&lt;/span&gt;

        &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;customerData&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;cookies&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;getCookie&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;customerData&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;customerData&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!==&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;nx&quot;&gt;customerData&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;cookies&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;parseJson&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;customerData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
            &lt;span class=&quot;nx&quot;&gt;dataLayer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;push&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;customerData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
            &lt;span class=&quot;nx&quot;&gt;cookies&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;delCookie&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;customerData&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;This may not turn out to be the 100% best way of solving this particular problem, but having thoroughly tested with various types of customer data I have found it to be consistently reliable.&lt;/p&gt;

&lt;p&gt;Thanks for reading and please feel free to comment if you have any suggestions or improvements.&lt;/p&gt;
</description>
        <pubDate>Mon, 08 May 2017 09:00:00 +0000</pubDate>
        <link>http://adammoss.co.uk/magentofox/private-data-tracking-in-magento-2/</link>
        <guid isPermaLink="true">http://adammoss.co.uk/magentofox/private-data-tracking-in-magento-2/</guid>
        
        
        <category>magento</category>
        
        <category>magento2</category>
        
      </item>
    
      <item>
        <title>CreareSEO 1.5 for Magento 1</title>
        <description>&lt;p&gt;It’s fair to say that CreareSEO has been left on the shelf for quite some time due to change of ownership and other commitments. I was able to dedicate some time to make some important updates over the last month so I’m happy to announce version 1.5 is now available on GitHub: &lt;a href=&quot;https://github.com/adampmoss/CreareSEO/releases/tag/1.5&quot;&gt;CreareSEO 1.5&lt;/a&gt;&lt;/p&gt;

&lt;h3 id=&quot;html-sitemap-improvements&quot;&gt;HTML Sitemap Improvements&lt;/h3&gt;
&lt;p&gt;The HTML sitemap module has been refactored significantly to reduce server load time. There is now no limit on the depth of the category tree so all categories can be listed in a nested unordered list.&lt;/p&gt;

&lt;p&gt;I have also taken the decision to remove the skin/css styling that came bundled in the package because I wanted the styling to be as ‘vanilla’ as possible, allowing devs to style in their own way if they wish. I understand this may mess up the default styling slightly for some people (sorry!).&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/posts/sitemap.png&quot; alt=&quot;HTML Sitemap Front&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Also in this version you can specify your own HTML Sitemap page title, meta description and in-page description.&lt;/p&gt;

&lt;h3 id=&quot;feature-categories-in-default-product-titles--meta-descriptions&quot;&gt;Feature: Categories in Default Product Titles &amp;amp; Meta Descriptions&lt;/h3&gt;

&lt;p&gt;A &lt;a href=&quot;https://github.com/adampmoss/CreareSEO/issues/33&quot;&gt;long-standing request&lt;/a&gt; is finally here. When creating your default page titles / meta descriptions for products you can now use the following new tags:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;[first_category]&lt;/code&gt; outputs the first category found belonging to the product&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;[categories]&lt;/code&gt; outputs all categories found belonging to a product in a comma-separated list&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For example the following configuration:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/posts/categories-in-meta.png&quot; alt=&quot;Categories in Meta Data Config&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Would output:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;title&amp;gt;&lt;/span&gt;Batman T Shirt - Batman Merch&lt;span class=&quot;nt&quot;&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;meta&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;description&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;content=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Batman T Shirt - Batman Merch, T Shirts&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h3 id=&quot;cms-canonical-tag-configuration&quot;&gt;CMS Canonical Tag Configuration&lt;/h3&gt;

&lt;p&gt;The previous logic for setting canonical tags on CMS pages was flawed because it could switch depending on whether you’re on a secure page or not. 1.5 allows you to specify in the config whether you want to canonicalise http or https protocols, and also gives you the option to add or remove the trailing slash.&lt;/p&gt;

&lt;p&gt;Go to &lt;strong&gt;System &amp;gt; CreareSEO &amp;gt; General Settings&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/posts/cms-canonical.png&quot; alt=&quot;CMS Canonical Config&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;other-updates&quot;&gt;Other Updates&lt;/h3&gt;

&lt;p&gt;Patch SUPEE-8788 caused a couple of issues with Magento’s admin and product page canonical redirects which were swiftly dealt with by the community. A big thanks to &lt;a href=&quot;https://github.com/unxsist&quot;&gt;Jeroen Nijhuis&lt;/a&gt;, &lt;a href=&quot;https://github.com/lfolco&quot;&gt;Laura Folco&lt;/a&gt; and &lt;a href=&quot;https://github.com/sprankhub&quot;&gt;Simon Sprankel&lt;/a&gt; for their contributions and support.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/adampmoss/CreareSEO/pull/78&quot;&gt;PR #78&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/adampmoss/CreareSEO/pull/81&quot;&gt;PR #81&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
        <pubDate>Sat, 05 Nov 2016 09:00:00 +0000</pubDate>
        <link>http://adammoss.co.uk/magentofox/magento-creareseo-1-5/</link>
        <guid isPermaLink="true">http://adammoss.co.uk/magentofox/magento-creareseo-1-5/</guid>
        
        
        <category>magento</category>
        
        <category>creareseo</category>
        
      </item>
    
      <item>
        <title>Magento 1 - Registration Form Not Working</title>
        <description>&lt;p&gt;I’m gonna try and get straight to the point with the post because this actually quite an old problem! However, it recently came to my attention just how un-documented my eventual solution was.&lt;/p&gt;

&lt;h3 id=&quot;whats-the-bug&quot;&gt;What’s the bug?&lt;/h3&gt;

&lt;p&gt;You try and register or login as a customer using your website’s frontend and the page simply refreshes without an error message, or even a damn apology. The bug is best known for its presence in Magento CE 1.9.2.2, EE 1.14.2.3 (I think) and the wonderful, beautiful patch SUPEE-6788.&lt;/p&gt;

&lt;p&gt;The solution that works for a lot of people is already very well documented here so I’ll not bother repeating what has already been said. In a nutshell it’s to do with hidden form keys not existing in frontend forms due to custom themes. &lt;a href=&quot;https://www.dudesquare.nl/blog/2015/11/02/customer-registration-not-working-magento-1-9-2-2/&quot;&gt;https://www.dudesquare.nl/blog/2015/11/02/customer-registration-not-working-magento-1-9-2-2/&lt;/a&gt;&lt;/p&gt;

&lt;h3 id=&quot;that-didnt-work-for-me-what-else-you-got&quot;&gt;That didn’t work for me! What else you got??&lt;/h3&gt;

&lt;p&gt;You have all your form keys in place and the error persists, and let me guess, you now have about as much hair as Stone Cold Steve Austin? The issue (for me at least) ended up being to do with session cookies messing up the form keys.&lt;/p&gt;

&lt;p&gt;Using Xdebug I could see that the form key that gets sent by the registration form was failing its vaildation check because by the time the &lt;code class=&quot;highlighter-rouge&quot;&gt;createPostAction&lt;/code&gt; was called a new form key had been created!&lt;/p&gt;

&lt;p&gt;What caused this to happen? It turned out that somehow our site had created two &lt;code class=&quot;highlighter-rouge&quot;&gt;frontend&lt;/code&gt; session cookies and a different one was being used either side of the form POST. Helpful eh?&lt;/p&gt;

&lt;h4 id=&quot;to-fix-this-there-are-two-solutions&quot;&gt;To fix this there are two solutions…&lt;/h4&gt;

&lt;p&gt;1) If your site is fairly stable you can delete the duplicate &lt;code class=&quot;highlighter-rouge&quot;&gt;frontend&lt;/code&gt; session cookie. Ideally the remaining cookie will be something like: &lt;strong&gt;yourdomain.com&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In Chrome this can be done by using &lt;strong&gt;Element Inspector &amp;gt; Application &amp;gt; Storage &amp;gt; Cookies&lt;/strong&gt;. Click on the domain and then find the duplicate cookie. Right-click and delete it.&lt;/p&gt;

&lt;p&gt;2) Alternatively, go to &lt;strong&gt;System &amp;gt; Configuration &amp;gt; General &amp;gt; Web&lt;/strong&gt; and add your domain URL to the Cookie Domain field as shown below. Credit: &lt;a href=&quot;http://stackoverflow.com/a/37955615/750537&quot;&gt;Phil Birnie on Stack Overflow&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/posts/cookie-domain.png&quot; alt=&quot;Set Cookie Domain&quot; /&gt;&lt;/p&gt;

&lt;p&gt;This will guarantee a single domain for your frontend cookies meaning that the other will simply be ignored.&lt;/p&gt;
</description>
        <pubDate>Mon, 24 Oct 2016 18:00:00 +0000</pubDate>
        <link>http://adammoss.co.uk/magentofox/magento-registration-form-not-working/</link>
        <guid isPermaLink="true">http://adammoss.co.uk/magentofox/magento-registration-form-not-working/</guid>
        
        
        <category>magento</category>
        
      </item>
    
      <item>
        <title>Half Marathon to a Marathon in 5 Weeks</title>
        <description>&lt;p&gt;I decided to write this post because I wanted to describe how I went from being a seasoned half marathon runner to running a full marathon in the space of 5 weeks. Just for the record… I’m in no way offering this as “training advice” or anything like that as I’m not qualified to do so, but my story may offer some insight into what to expect if you’re as impatient as me.&lt;/p&gt;

&lt;p&gt;A tiny bit of background… I’ve been running half marathons since 2012 and at the time of writing have ran 8 half marathon events across the UK with an average time around the 1:42 mark. I find them relatively easy and really enjoyable.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;“I got the buzz back for running and I suddenly wanted… no, &lt;em&gt;needed&lt;/em&gt; to do a full marathon”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I’m the kind of person who goes in and out of running phases. It’s not something I do all-year round, but I’ll do it for a few months at a time until I get a bit bored or complete a particular goal such as a race event. I guess you could call me a part-time distance runner.&lt;/p&gt;

&lt;p&gt;So anyway, I got back into running after starting my new job as I found myself with a lot of spare time on my own in the evenings, and I was completing 5-8 mile runs most nights. Out of nowhere I got the buzz back for running and I suddenly wanted… no, &lt;em&gt;needed&lt;/em&gt; to do a full marathon.&lt;/p&gt;

&lt;h3 id=&quot;the-pre-run&quot;&gt;The Pre-Run&lt;/h3&gt;

&lt;p&gt;I browsed the Internet for upcoming marathons and the smart thing to do would have been to find one in the autumn period, giving me ample time to train and prepare. I realised however that waiting too long is not something I can do - I would surely lose interest if the race wasn’t for another 5-6 months.&lt;/p&gt;

&lt;p&gt;As soon as I discovered the &lt;a href=&quot;http://www.runrocknroll.com/liverpool/&quot;&gt;Rock n’ Roll Liverpool&lt;/a&gt; marathon I knew that was the one. The location, the time of year, the cool branding. The only issue was that it was only 6 weeks away…&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;“running around a 5 mile reservoir 4 times is boring as hell”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Before booking anything I decided to do a 20-mile personal run to see if I had what it takes to even get close to that kind of distance, so I set out one freezing cold Sunday morning and ran 4 (and a bit) laps around a local reservoir called Draycote Water. I figured that if I can complete 20 miles on my own I will be able to determine whether I’d have had enough left in the tank to complete the last 6.2 miles.&lt;/p&gt;

&lt;p&gt;It must be said that, while it’s a decent, flat-ish route, running around a 5 mile reservoir 4 times is boring as hell!&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/posts/draycote.png&quot; alt=&quot;Draycote Water Run&quot; /&gt;&lt;/p&gt;

&lt;p&gt;I completed the run and felt confident enough in my own ability that I could complete the 26.2 miles, particularly in a race day environment reaching fever-pitch, so I booked Liverpool RnR.&lt;/p&gt;

&lt;h3 id=&quot;the-training&quot;&gt;The Training&lt;/h3&gt;

&lt;p&gt;In the 5 weeks that I gave myself to prepare for this event I can honestly say that I didn’t really make the most of the time I had. I trained, but I didn’t train as much as I should have. Let’s face it, no amount of training was really going to be enough in the timeframe I allowed myself, but I still found myself not quite making the most of the time I had available.&lt;/p&gt;

&lt;h4 id=&quot;week-1&quot;&gt;Week 1&lt;/h4&gt;
&lt;ul&gt;
  &lt;li&gt;Sunday: 5.85 miles&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;week-2&quot;&gt;Week 2&lt;/h4&gt;
&lt;ul&gt;
  &lt;li&gt;Tuesday: 7.9 miles&lt;/li&gt;
  &lt;li&gt;Wednesday: 5.27 miles&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;week-3&quot;&gt;Week 3&lt;/h4&gt;
&lt;ul&gt;
  &lt;li&gt;Monday: 10.28 miles&lt;/li&gt;
  &lt;li&gt;Saturday: 6.7 miles&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;week-4&quot;&gt;Week 4&lt;/h4&gt;
&lt;ul&gt;
  &lt;li&gt;Tuesday: 4.21 miles&lt;/li&gt;
  &lt;li&gt;Thursday: 6.3 miles&lt;/li&gt;
  &lt;li&gt;Friday: 4.12 miles&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;week-5&quot;&gt;Week 5&lt;/h4&gt;
&lt;ul&gt;
  &lt;li&gt;Monday: 10.92 miles&lt;/li&gt;
  &lt;li&gt;Sunday: Race Day!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Not exactly comprehensive eh? I was doing other training around this such as my normal gym exercises and a long-distance cycle, but looking back this was very relaxed preparation. The only run of any note when it comes to serious distance was that 21 miler I did before booking the event at all. Most marathon training schedules will see you achieve several 18+ mile runs in order to condition your legs (and mind) for the demands that a marathon exerts on the body.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;“Most marathon training schedules will see you achieve several 18+ mile runs to condition your legs”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Despite all this, race day came along and I went into the race full of confidence and determination. Nothing was going to stop me.&lt;/p&gt;

&lt;h3 id=&quot;the-race-day&quot;&gt;The Race Day&lt;/h3&gt;

&lt;p&gt;Sunday May 29th 2016 was a beautiful day, the sun was shining and the temperature was around 20 degrees, warm but not hot. I completed the marathon in 4:04:48, about 5 minutes slower than I had wanted but that didn’t matter too much, I was just happy to have completed ‘near’ my anticipated time.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/posts/results.png&quot; alt=&quot;Marathon Results&quot; /&gt;&lt;/p&gt;

&lt;p&gt;I came out of the run injury-free but with very sore joints. The last 7 miles were particularly painful on my ankles, hips and knee joints even though my muscles didn’t seem to be too tired as I was able to pick up the pace towards the end.&lt;/p&gt;

&lt;p&gt;In terms of difficulty I would say it is probably 3x more difficult than a half marathon. Not only is the physical impact deeper and more prolonged, but keeping the mind engaged and focused for 4 hours was very difficult. Towards the last few miles you stop being able to enjoy the views and the atmosphere as every thought turns to whatever is hurting most on your body and “when can I stop running?”.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;“it is probably 3x more difficult than a half marathon”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Perhaps with better preparation those miles would have been less painful, but in the end I was never in dire straits. I didn’t have to stop and walk (though I did have to stop for a piss 4 times!) and I kept a consistent pace throughout. Taking everything into account I really couldn’t have ran it any better, and the race as a whole, I absolutely loved it.&lt;/p&gt;

&lt;h3 id=&quot;afterthoughts&quot;&gt;Afterthoughts&lt;/h3&gt;

&lt;p&gt;It was 100% the right decision for me to have done what I did. In two days time I was recovered and back to playing football with a great experience under my belt. Not completing the race was never an option for me. Rightly or wrongly I would’ve dragged myself over the finish line if I had to. Luckily it never came to that!&lt;/p&gt;

&lt;p&gt;So why am I telling you all this? Well, I wanted to write this so that other people who are wanting to upgrade to a full marathon can take something out of my experience.&lt;/p&gt;

&lt;p&gt;I want people to know that it &lt;em&gt;can&lt;/em&gt; be done with the right combination of experience, training, health, fitness and luck, but I wouldn’t generally recommend it unless you have full confidence in what you’re doing. Find a good training plan and do things properly, but most of all enjoy it!&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/posts/finished.png&quot; alt=&quot;Finished&quot; /&gt;&lt;/p&gt;
</description>
        <pubDate>Sun, 16 Oct 2016 13:00:00 +0000</pubDate>
        <link>http://adammoss.co.uk/blog/half-marathon-to-a-marathon-in-5-weeks/</link>
        <guid isPermaLink="true">http://adammoss.co.uk/blog/half-marathon-to-a-marathon-in-5-weeks/</guid>
        
        
        <category>blog</category>
        
      </item>
    
      <item>
        <title>Google Shopping - Outputting Sale Price Effective Date with PHP</title>
        <description>&lt;p&gt;In a recent project I was building a good ol’ fashioned Google Shopping feed, something I’ve done more times than I’ve had hot dinners, except this time I encountered a new attribute called &lt;em&gt;sale_price_effective_date&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;After a swift read of &lt;a href=&quot;https://support.google.com/merchants/answer/1196048?hl=en-GB&quot;&gt;Google’s documentation&lt;/a&gt; I realised it wasn’t as straightforward as other PHP dates I have outputted in the past. There’s a timezone… and a random T right in the middle, and there’s a sale FROM and TO date!!&lt;/p&gt;

&lt;p&gt;Ultimately, Google wants something like this:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;2011-03-01T16:00-0800/2011-03-03T16:00-0800
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;As a Magento user I’ll show you the function I used to get to this hideous string of data. I’ve stripped it down slightly for simplicity.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-php&quot; data-lang=&quot;php&quot;&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;getSalePriceEffectiveDate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$product&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// return if no sale price
&lt;/span&gt;        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$product&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getSpecialPrice&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

        &lt;span class=&quot;nv&quot;&gt;$currentTimeString&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;strtotime&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;now&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

        &lt;span class=&quot;nv&quot;&gt;$saleFromTimeString&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$product&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getSpecialFromDate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
            &lt;span class=&quot;o&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;strtotime&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$product&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getSpecialFromDate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
            &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$currentTimeString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;nv&quot;&gt;$saleToTimeString&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$product&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getSpecialToDate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
            &lt;span class=&quot;o&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;strtotime&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$product&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getSpecialToDate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
            &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$saleToTimeString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;

            &lt;span class=&quot;nv&quot;&gt;$from&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;googleDate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$saleFromTimeString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
            &lt;span class=&quot;nv&quot;&gt;$to&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;googleDate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$saleToTimeString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

            &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$from&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;/&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$to&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;googleDate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$timeString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;date&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Y-m-d\TH:iO&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$timeString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The key part here is how each date is formatted based on Google’s requirements:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;date(&quot;Y-m-d\TH:iO&quot;, $saleFromTimeString)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code class=&quot;highlighter-rouge&quot;&gt;\T&lt;/code&gt; is what allows the T to intersect the date and time, and the &lt;code class=&quot;highlighter-rouge&quot;&gt;O&lt;/code&gt; outputs the timezone difference in hours between the server location and GMT.&lt;/p&gt;

&lt;p&gt;Another sneaky part of the script is how I’ve set the &lt;code class=&quot;highlighter-rouge&quot;&gt;$saleFromTimeString&lt;/code&gt; as the current time in case one hasn’t been set. If there’s an end date then surely there has to be a start date right?&lt;/p&gt;

&lt;p&gt;It’s all relatively simple but if you’re not familiar with all aspects of the PHP &lt;code class=&quot;highlighter-rouge&quot;&gt;date()&lt;/code&gt; function it can be tricky! Hopefully this comes in useful for someone.&lt;/p&gt;
</description>
        <pubDate>Thu, 13 Oct 2016 20:00:00 +0000</pubDate>
        <link>http://adammoss.co.uk/magentofox/google-shopping-outputting-sale-price-effective-date-with-php/</link>
        <guid isPermaLink="true">http://adammoss.co.uk/magentofox/google-shopping-outputting-sale-price-effective-date-with-php/</guid>
        
        
        <category>magento</category>
        
        <category>google-shopping</category>
        
      </item>
    
      <item>
        <title>Magento 1 - Extending Core JavaScript with Prototype</title>
        <description>&lt;p&gt;The Majority of Magento 1’s JavaScript is written in the widely disliked, DOM-extending, Prototype.js framework. Launched in 2005, Prototype has been around for a long-ass time and is now struggling to maintain relevance in the face of modern, package-based frameworks like React.js.&lt;/p&gt;

&lt;p&gt;For Magento 1 developers however it still plays a big part of every day life and when customising Magento there is often the need to interact with the core JavaScript files. When extending skin JavaScript the temptation is to put a modified copy of the file into your theme, but in the instance of an upgrade this could heavily stack your workload.&lt;/p&gt;

&lt;p&gt;Luckily, Prototype makes it easy to change the output and input of class methods using two key methods of its own:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://api.prototypejs.org/language/Class/prototype/addMethods/&quot;&gt;Class#addMethods&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://prototypejs.org/doc/latest/language/Function/prototype/wrap/&quot;&gt;Function#wrap&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In an attempt to demystify this, I’m gonna go through how to put this into practice extending a Magento 1 core Prototype class.&lt;/p&gt;

&lt;h3 id=&quot;addmethods&quot;&gt;addMethods&lt;/h3&gt;

&lt;p&gt;addMethods allows you to take a class that has already been created and initialised and, as the name suggests, add new methods. These new methods can then be accessed by the object instance. It also allows us to overwrite existing methods simply by defining them again. Let’s take a look at an example:&lt;/p&gt;

&lt;p&gt;Let’s say we want to add ‘plus tax’ to the price presented by a configurable product. Well, in the &lt;code class=&quot;highlighter-rouge&quot;&gt;Product.Config&lt;/code&gt; class found in &lt;strong&gt;/js/varien/configurable.js&lt;/strong&gt; the method that formats the price before it is presented is (unsurprisingly) &lt;code class=&quot;highlighter-rouge&quot;&gt;formatPrice&lt;/code&gt;. I’m going to use &lt;code class=&quot;highlighter-rouge&quot;&gt;addMethods&lt;/code&gt; to change how this is output.&lt;/p&gt;

&lt;p&gt;The first step is to create a module that will include a custom JS file on the product page - I’m going to assume you know how to do this bit. I’ve created a file called custom.js and put it into the path below:&lt;/p&gt;

&lt;h4 id=&quot;skinfrontendbasedefaultjsmagentofoxcustomjs&quot;&gt;skin/frontend/base/default/js/magentofox/custom.js&lt;/h4&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-js&quot; data-lang=&quot;js&quot;&gt;&lt;span class=&quot;nx&quot;&gt;Product&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Config&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;addMethods&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;

    &lt;span class=&quot;na&quot;&gt;formatPrice&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;price&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;showSign&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;){&lt;/span&gt;
        &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;str&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;''&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;price&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;parseFloat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;price&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;showSign&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;){&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;price&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;){&lt;/span&gt;
                &lt;span class=&quot;nx&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'-'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
                &lt;span class=&quot;nx&quot;&gt;price&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;price&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;nx&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'+'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

        &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;roundedPrice&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;Math&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;round&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;price&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;toString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;

        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;prices&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;prices&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;roundedPrice&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;nx&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;prices&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;roundedPrice&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;nx&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;priceTemplate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;evaluate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;price&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;price&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;toFixed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)});&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;str&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Translator&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;translate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot; plus tax&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;All I’ve done here is replicated the method in its entirety and customised it where necessary. If I didn’t replicate the method then the functionality in the original method would have been lost. In fact the only line I’ve changed is this part: &lt;code class=&quot;highlighter-rouge&quot;&gt;return str + Translator.translate(&quot; plus tax&quot;);&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This achieves the end goal without having to edit or duplicate the whole of the original file. Easy!&lt;/p&gt;

&lt;h3 id=&quot;wrap&quot;&gt;wrap&lt;/h3&gt;

&lt;p&gt;Wrap is kinda similar to addMethods but also very different. Rather than taking place on the class definition, wrap targets the method itself. Rather like &lt;a href=&quot;/magentofox/magento-2-basics-part-6-using-plugins/&quot;&gt;plugins in Magento 2&lt;/a&gt;, wrap allows you to modify the arguments before a method is called, completely change the functionality of a method &lt;em&gt;and&lt;/em&gt; change the output of any given method.&lt;/p&gt;

&lt;p&gt;Let’s redo the last example again by adding ‘plus tax’ to the end of the string, but this time we want to change the value of the price going into the method so it’s always 600. Yeah, you’d never need to do this but it demonstrates the point pretty well:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-js&quot; data-lang=&quot;js&quot;&gt;&lt;span class=&quot;nx&quot;&gt;Product&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Config&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;prototype&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;formatPrice&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Product&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Config&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;prototype&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;formatPrice&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;wrap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;originalMethod&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;price&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;showSign&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;price&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;600&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;str&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;originalMethod&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;price&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;showSign&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;str&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Translator&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;translate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot; plus tax&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;So what’s going on above? Well once we’re inside the wrap function there’s a new function declared: &lt;code class=&quot;highlighter-rouge&quot;&gt;function(originalMethod, price, showSign)&lt;/code&gt;. The first argument is always the method itself, and the following arguments are those that should get passed to the method. That means that as soon as we are inside this function we have access to those arguments.&lt;/p&gt;

&lt;p&gt;On the next line I’ve decided to change the price so that it’s always 600. Now I can pass my changed argument into the method in question which happens on the next line &lt;code class=&quot;highlighter-rouge&quot;&gt;var str = originalMethod(price, showSign);&lt;/code&gt;. The method will now run as normal and return whatever it returns - this gets saved into my newly created &lt;code class=&quot;highlighter-rouge&quot;&gt;str&lt;/code&gt; variable.&lt;/p&gt;

&lt;p&gt;Finally I’m going to return the function properly (after it has now successfully ran with all the functionality needed) and I’m going to add my text to the end.&lt;/p&gt;

&lt;p&gt;This example is rather extreme in that modifies the before and after parts of the &lt;code class=&quot;highlighter-rouge&quot;&gt;formatPrice&lt;/code&gt; method.&lt;/p&gt;

&lt;h3 id=&quot;summary&quot;&gt;Summary&lt;/h3&gt;

&lt;p&gt;There is also another method called &lt;a href=&quot;http://api.prototypejs.org/language/Object/extend/&quot;&gt;Object.extend&lt;/a&gt; that allows core classes and methods to be extended without touching the core, but I have left this out of this article because it involves the creation of a new class definitions which is slightly different to what I’m trying to show. Using this would mean having to change the class instances across Magento which could be more time consuming.&lt;/p&gt;

&lt;p&gt;Hope you enjoyed the post, feel free to leave comments.&lt;/p&gt;
</description>
        <pubDate>Wed, 20 Apr 2016 20:00:00 +0000</pubDate>
        <link>http://adammoss.co.uk/magentofox/magento1-extending-core-javascript-with-prototype/</link>
        <guid isPermaLink="true">http://adammoss.co.uk/magentofox/magento1-extending-core-javascript-with-prototype/</guid>
        
        
        <category>magento</category>
        
      </item>
    
      <item>
        <title>Magento 2 Basics Part 6 - Using Plugins</title>
        <description>&lt;p&gt;Plugins are a fantastic way of extending Magento 2 without the need for class rewrites by allowing you to modify the input and output of (most) methods belonging to the Magento 2 framework. For those familiar with Wordpress development the theory is similar to the action/hook format.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;/magentofox/magento-2-basics-part-1-setting-up-your-module/&quot;&gt;Part 1 - Setting up your module&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/magentofox/magento-2-basics-part-2-creating-a-frontend-controller/&quot;&gt;Part 2 - Creating a frontend controller&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/magentofox/magento-2-basics-part-3-creating-a-helper/&quot;&gt;Part 3 - Creating a helper&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/magentofox/magento-2-basics-part-4-creating-an-observer/&quot;&gt;Part 4 - Creating an observer&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/magentofox/magento-2-basics-part-5-creating-an-admin-page/&quot;&gt;Part 5 - Creating an admin page&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Part 6 - Using plugins&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In this tutorial I’m going to take a method and show you how it can be modified using the three plugin types:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;before&lt;/li&gt;
  &lt;li&gt;after&lt;/li&gt;
  &lt;li&gt;around&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;step-1---create-magefoxexampleetcdixml&quot;&gt;Step 1 - Create Magefox/Example/etc/di.xml&lt;/h3&gt;

&lt;p&gt;In the example below I have declared two classes I want to “observe” with my plugins, and within each I have entered a plugin entry that specifies the class that I want to use in the “type” attribute.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-xml&quot; data-lang=&quot;xml&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;config&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;xmlns:xsi=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;http://www.w3.org/2001/XMLSchema-instance&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;xsi:noNamespaceSchemaLocation=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;urn:magento:framework:ObjectManager/etc/config.xsd&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;type&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Magento\Theme\Block\Html\Breadcrumbs&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;plugin&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;changeBreadcrumbs&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;type=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Magefox\Example\Plugin\BreadcrumbsPlugin&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;sortOrder=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;1&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;disabled=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;false&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/type&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;type&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Magento\Cms\Model\Page&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;plugin&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;changePage&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;type=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Magefox\Example\Plugin\PagePlugin&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;sortOrder=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;1&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;disabled=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;false&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/type&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/config&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The naming convention I’ve used for my plugin means that I can identify quickly that my plugin is concerned with a page model. I don’t know for sure if this is the suggested naming convention but it is in line with Magento’s own dev docs from what I’ve seen.&lt;/p&gt;

&lt;p&gt;A couple of important points:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;First argument must always be the observed class (e.g. &lt;strong&gt;Magento\Theme\Block\Html\Breadcrumbs&lt;/strong&gt;) - this gives us access to all the parent classes methods.&lt;/li&gt;
  &lt;li&gt;The following arguments are the arguments passed by default into the method&lt;/li&gt;
  &lt;li&gt;Plugins can be prioritised using the sortOrder attribute. They are ran in ascending order.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now the file where the magic happens. Plugin classes do not extend or interface any other classes, though they must still use dependency injection if you want to access other objects.&lt;/p&gt;

&lt;h4 id=&quot;before---magefoxexamplepluginbreadcrumbspluginphp&quot;&gt;Before - Magefox\Example\Plugin\BreadcrumbsPlugin.php&lt;/h4&gt;

&lt;p&gt;“Before” allows you to modify the arguments of a chosen method, which obviously won’t do much if the method has no arguments! Let’s take a look at the following example:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-php&quot; data-lang=&quot;php&quot;&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;namespace&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Magefox\Example\Plugin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;BreadcrumbsPlugin&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;beforeAddCrumb&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;\Magento\Theme\Block\Html\Breadcrumbs&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$subject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$crumbName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$crumbInfo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$crumbInfo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'label'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Privacy and Cookie Policy&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;nv&quot;&gt;$crumbInfo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'label'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Something else&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$crumbName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$crumbInfo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;In this example I’m taking the two arguments $crumbName and $crumbInfo and I’m checking if the label is “Privacy” then change it to literally something else. Then I’m returning the arguments in the exact correct format at the end of the function. Real simple eh?&lt;/p&gt;

&lt;h4 id=&quot;after---magefoxexamplepluginpagepluginphp&quot;&gt;After - Magefox\Example\Plugin\PagePlugin.php&lt;/h4&gt;

&lt;p&gt;The “after” option allows you to modify the data that is returned by the method in question. I’ve chosen a different class this time because the Breadcrumbs class isn’t the best example of how this works.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-php&quot; data-lang=&quot;php&quot;&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;namespace&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Magefox\Example\Plugin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;PagePlugin&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;afterGetContentHeading&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;\Magento\Cms\Model\Page&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$page&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$contentHeading&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;This is the &quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$contentHeading&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The second argument is always the value returned by the original method, we simply take that result and do what we want with it. In this case I’m just prefixing some text to the string that is returned.&lt;/p&gt;

&lt;h4 id=&quot;around---magefoxexamplepluginbreadcrumbspluginphp&quot;&gt;Around - Magefox\Example\Plugin\BreadcrumbsPlugin.php&lt;/h4&gt;

&lt;p&gt;Our “around” method takes at least two arguments:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;$subject&lt;/code&gt; The class being listened to&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;$proceed&lt;/code&gt; The next plugin or method in line based on sortOrder&lt;/li&gt;
  &lt;li&gt;The rest of the arguments based on the methods&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;We then have the opportunity within our method to modify the arguments AND change the returned value. Let’s go back to our breadcrumbs class:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-php&quot; data-lang=&quot;php&quot;&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;namespace&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Magefox\Example\Plugin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;BreadcrumbsPlugin&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;aroundAddCrumb&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;\Magento\Theme\Block\Html\Breadcrumbs&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$subject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;\Closure&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$proceed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$crumbName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$crumbInfo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$crumbInfo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'label'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Privacy and Cookie Policy&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;nv&quot;&gt;$crumbInfo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'label'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Something else&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

        &lt;span class=&quot;nv&quot;&gt;$result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$proceed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$crumbName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$crumbInfo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

        &lt;span class=&quot;cm&quot;&gt;/* I now have the opportunity to influence what is returned by our method. */&lt;/span&gt;

        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;I start by doing my thing to the arguments as per I previous example, and then I’ve highlighted the area where I have the opportunity to change the result. As the method returns an instance of the class there’s not much more I can do to illustrate this.&lt;/p&gt;

&lt;p&gt;Plugins are a major step forward for Magento 2 so I hope you enjoy using them!&lt;/p&gt;
</description>
        <pubDate>Wed, 16 Mar 2016 14:00:00 +0000</pubDate>
        <link>http://adammoss.co.uk/magentofox/magento-2-basics-part-6-using-plugins/</link>
        <guid isPermaLink="true">http://adammoss.co.uk/magentofox/magento-2-basics-part-6-using-plugins/</guid>
        
        
        <category>magento2</category>
        
        <category>magento</category>
        
      </item>
    
      <item>
        <title>Magento 2 Basics Part 5 - Creating an Admin Page</title>
        <description>&lt;p&gt;Adding elements to the admin area is always a requirement when working with custom modules as you need to let your user content-manage and configure their functionality.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;/magentofox/magento-2-basics-part-1-setting-up-your-module/&quot;&gt;Part 1 - Setting up your module&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/magentofox/magento-2-basics-part-2-creating-a-frontend-controller/&quot;&gt;Part 2 - Creating a frontend controller&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/magentofox/magento-2-basics-part-3-creating-a-helper/&quot;&gt;Part 3 - Creating a helper&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/magentofox/magento-2-basics-part-4-creating-an-observer/&quot;&gt;Part 4 - Creating an observer&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Part 5 - Creating an admin page&lt;/strong&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/magentofox/magento-2-basics-part-6-using-plugins/&quot;&gt;Part 6 - Using plugins&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Adding sections to the admin area is in some ways very different to Magento 1. In this tutorial I’m not going to cover admin grids, instead I’m going to focus on creating a grid-less admin page and adding to the configuration.&lt;/p&gt;

&lt;h2 id=&quot;configuration&quot;&gt;Configuration&lt;/h2&gt;

&lt;p&gt;The Magento 2 configuration is now found in &lt;strong&gt;Stores &amp;gt; Settings &amp;gt; Configuration&lt;/strong&gt;, however a familiar file is needed to add to this:&lt;/p&gt;

&lt;h3 id=&quot;step-1---create-magefoxexampleetcadminhtmlsystemxml&quot;&gt;Step 1 - Create Magefox/Example/etc/adminhtml/system.xml&lt;/h3&gt;

&lt;p&gt;In the example below I have created a new tab called “Magento Fox” with a section called “Settings” underneath. There is then a option group called “Settings” with a single Yes/No field called “Show Something?”.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-xml&quot; data-lang=&quot;xml&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;config&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;xmlns:xsi=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;http://www.w3.org/2001/XMLSchema-instance&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;xsi:noNamespaceSchemaLocation=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;urn:magento:module:Magento_Config:etc/system_file.xsd&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;system&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;tab&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;magefox&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;translate=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;label&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;sortOrder=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;200&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;nt&quot;&gt;&amp;lt;label&amp;gt;&lt;/span&gt;Magento Fox&lt;span class=&quot;nt&quot;&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;/tab&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;section&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;magefox&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;translate=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;label&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;type=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;text&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;sortOrder=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;110&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;showInDefault=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;1&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;showInWebsite=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;1&quot;&lt;/span&gt;
                 &lt;span class=&quot;na&quot;&gt;showInStore=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;1&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;nt&quot;&gt;&amp;lt;label&amp;gt;&lt;/span&gt;Settings&lt;span class=&quot;nt&quot;&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;nt&quot;&gt;&amp;lt;tab&amp;gt;&lt;/span&gt;magefox&lt;span class=&quot;nt&quot;&gt;&amp;lt;/tab&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;nt&quot;&gt;&amp;lt;resource&amp;gt;&lt;/span&gt;Magefox_Example::settings&lt;span class=&quot;nt&quot;&gt;&amp;lt;/resource&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;nt&quot;&gt;&amp;lt;group&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;settings&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;translate=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;label&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;type=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;text&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;sortOrder=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;120&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;showInDefault=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;1&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;showInWebsite=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;1&quot;&lt;/span&gt;
                   &lt;span class=&quot;na&quot;&gt;showInStore=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;1&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
                &lt;span class=&quot;nt&quot;&gt;&amp;lt;label&amp;gt;&lt;/span&gt;Settings&lt;span class=&quot;nt&quot;&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;
                &lt;span class=&quot;nt&quot;&gt;&amp;lt;field&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;showsomething&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;translate=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;label&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;type=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;select&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;sortOrder=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;10&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;showInDefault=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;1&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;showInWebsite=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;1&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;showInStore=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;1&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
                    &lt;span class=&quot;nt&quot;&gt;&amp;lt;label&amp;gt;&lt;/span&gt;Show something?&lt;span class=&quot;nt&quot;&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;
                    &lt;span class=&quot;nt&quot;&gt;&amp;lt;source_model&amp;gt;&lt;/span&gt;Magento\Config\Model\Config\Source\Yesno&lt;span class=&quot;nt&quot;&gt;&amp;lt;/source_model&amp;gt;&lt;/span&gt;
                &lt;span class=&quot;nt&quot;&gt;&amp;lt;/field&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;nt&quot;&gt;&amp;lt;/group&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;/section&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/system&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/config&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;There are obviously tonnes more options you can choose from here - my suggestion is to look at the core modules system.xml to find the code you need for each field type. The options are basically the same as Magento 1 system.xml.&lt;/p&gt;

&lt;h3 id=&quot;step-2---create-magefoxexampleetcconfigxml&quot;&gt;Step 2 - Create Magefox/Example/etc/config.xml&lt;/h3&gt;

&lt;p&gt;Config.xml is back, except this time is for setting default configuration values only. At least it’s a lot more readable this time round!&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-xml&quot; data-lang=&quot;xml&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;config&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;xmlns:xsi=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;http://www.w3.org/2001/XMLSchema-instance&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;xsi:noNamespaceSchemaLocation=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;urn:magento:module:Magento_Store:etc/config.xsd&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;default&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;magefox&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;nt&quot;&gt;&amp;lt;settings&amp;gt;&lt;/span&gt;
                &lt;span class=&quot;nt&quot;&gt;&amp;lt;showsomething&amp;gt;&lt;/span&gt;1&lt;span class=&quot;nt&quot;&gt;&amp;lt;/showsomething&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;nt&quot;&gt;&amp;lt;/settings&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;/magefox&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/default&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/config&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h2 id=&quot;admin-pages&quot;&gt;Admin Pages&lt;/h2&gt;

&lt;p&gt;Creating an actual page in the admin requires a bit more work because (like the frontend) we have to create a controller using the admin route object and we have to build blocks to make the content. Grids &amp;amp; forms aside, this is how you do it:&lt;/p&gt;

&lt;h3 id=&quot;step-1---create-magefoxexampleetcadminhtmlroutesxml&quot;&gt;Step 1 - Create Magefox/Example/etc/adminhtml/routes.xml&lt;/h3&gt;

&lt;p&gt;First we create our admin route as I explained above (more XML!):&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-xml&quot; data-lang=&quot;xml&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;config&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;xmlns:xsi=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;http://www.w3.org/2001/XMLSchema-instance&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;xsi:noNamespaceSchemaLocation=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;urn:magento:framework:App/etc/routes.xsd&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;router&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;admin&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;route&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;magefox&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;frontName=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;magefox&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;nt&quot;&gt;&amp;lt;module&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Magefox_Example&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;/route&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/router&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/config&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h3 id=&quot;step-2---create-magefoxexampleetcadminhtmlmenuxml&quot;&gt;Step 2 - Create Magefox/Example/etc/adminhtml/menu.xml&lt;/h3&gt;

&lt;p&gt;Now you have to decide how you want people to be able to access your page by creating a conveniently named “menu.xml” file within etc/adminhtml.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-xml&quot; data-lang=&quot;xml&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;config&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;xmlns:xsi=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;http://www.w3.org/2001/XMLSchema-instance&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;xsi:noNamespaceSchemaLocation=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;urn:magento:module:Magento_Backend:etc/menu.xsd&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;menu&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;add&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Magefox_Example::magefox_stores&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;title=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Magento Fox&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;module=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Magefox_Example&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;sortOrder=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;50&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;parent=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Magento_Backend::stores&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;resource=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Magefox_Example::magefox_stores&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;add&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Magefox_Example::test&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;title=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Test&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;module=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Magefox_Example&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;sortOrder=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;10&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;parent=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Magefox_Example::magefox_stores&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;action=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;magefox/foxypage&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;resource=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Magefox_Example::test&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;add&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Magefox_Example::settings&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;title=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Settings&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;module=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Magefox_Example&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;sortOrder=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;20&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;parent=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Magefox_Example::magefox_stores&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;action=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;adminhtml/system_config/edit/section/magefox&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;resource=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Magefox_Example::settings&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/menu&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/config&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;In the example above I have added a new section to the “Stores” tab which is referenced in the first &amp;lt;add&amp;gt; node where it says &lt;strong&gt;parent=”Magento_Backend::stores”&lt;/strong&gt;. Underneath this I have then added a link to my new page which will be located at magefox/foxypage, and I’ve also linked to our new configuration page we created above.&lt;/p&gt;

&lt;h3 id=&quot;step-3---create-magefoxexampleetcaclxml&quot;&gt;Step 3 - Create Magefox/Example/etc/acl.xml&lt;/h3&gt;

&lt;p&gt;We need to ensure that our admin page can be restricted to certain users only. This can be done by making it available to the ACL object.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-xml&quot; data-lang=&quot;xml&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;config&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;xmlns:xsi=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;http://www.w3.org/2001/XMLSchema-instance&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;xsi:noNamespaceSchemaLocation=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;urn:magento:framework:Acl/etc/acl.xsd&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;acl&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;resources&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;nt&quot;&gt;&amp;lt;resource&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Magento_Backend::admin&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
                &lt;span class=&quot;nt&quot;&gt;&amp;lt;resource&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Magento_Backend::stores&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
                    &lt;span class=&quot;nt&quot;&gt;&amp;lt;resource&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Magefox_Example::magefox_stores&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;title=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Magento Fox&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;sortOrder=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;10&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
                        &lt;span class=&quot;nt&quot;&gt;&amp;lt;resource&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Magefox_Example::test&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;title=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Test&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;sortOrder=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;10&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
                        &lt;span class=&quot;nt&quot;&gt;&amp;lt;resource&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Magefox_Example::settings&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;title=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Settings&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;sortOrder=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;20&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
                    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/resource&amp;gt;&lt;/span&gt;
                &lt;span class=&quot;nt&quot;&gt;&amp;lt;/resource&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;nt&quot;&gt;&amp;lt;/resource&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;/resources&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/acl&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/config&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h3 id=&quot;step-4---create-magefoxexamplecontrolleradminhtmlfoxypageindexphp&quot;&gt;Step 4 - Create Magefox/Example/Controller/adminhtml/Foxypage/Index.php&lt;/h3&gt;

&lt;p&gt;We create our admin controller action in pretty much the same way as the frontend action, an execute method renders the page. An additional method here will also check that the user has the sufficient priveledges that we assigned above using ACL.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-php&quot; data-lang=&quot;php&quot;&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;namespace&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Magefox\Example\Controller\Adminhtml\Foxypage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Index&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;\Magento\Backend\App\Action&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;sd&quot;&gt;/**
     * Check if user has enough privileges
     *
     * @return bool
     */&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;protected&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;_isAllowed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;_authorization&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;isAllowed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'Magefox_Example::foxypage'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;sd&quot;&gt;/**
     * @return void
     */&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;execute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;_view&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;loadLayout&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;

        &lt;span class=&quot;nv&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;_setActiveMenu&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'Magefox_Example::foxypage'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;_view&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getPage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getConfig&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getTitle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;prepend&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'Foxy Admin Page'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;

        &lt;span class=&quot;nv&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;_addBreadcrumb&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'Stores'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'Stores'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;_addBreadcrumb&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'Foxy Admin Page'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'Foxy Admin Page'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;

        &lt;span class=&quot;nv&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;_view&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;renderLayout&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h3 id=&quot;step-5---create-magefoxexampleviewadminhtmllayoutmagefox_foxypage_indexxml&quot;&gt;Step 5 - Create Magefox/Example/view/adminhtml/layout/magefox_foxypage_index.xml&lt;/h3&gt;

&lt;p&gt;Just as we did with the front controller layout XML we do the same with the admin. All I’m doing here is adding a custom block to the content block:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-xml&quot; data-lang=&quot;xml&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;page&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;xmlns:xsi=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;http://www.w3.org/2001/XMLSchema-instance&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;xsi:noNamespaceSchemaLocation=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;urn:magento:framework:View/Layout/etc/page_configuration.xsd&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;referenceContainer&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;content&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;nt&quot;&gt;&amp;lt;block&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;hello.admin&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Magefox\Example\Block\Adminhtml\Hello&quot;&lt;/span&gt;
                   &lt;span class=&quot;na&quot;&gt;template=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;hello.phtml&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;/referenceContainer&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/page&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h3 id=&quot;step-6-create-magefoxexampleblockadminhtmlhellophp&quot;&gt;Step 6 Create Magefox\Example\Block\Adminhtml/Hello.php&lt;/h3&gt;

&lt;p&gt;Normal block class creation. I won’t add any methods as I think ypu’ve got the hang of it by now!&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-php&quot; data-lang=&quot;php&quot;&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;namespace&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Magefox\Example\Block\Adminhtml&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Hello&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;\Magento\Backend\Block\Template&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// methods here
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h3 id=&quot;step-7-create-magefoxexampleviewadminhtmltemplateshellophtml&quot;&gt;Step 7 Create Magefox/Example/view/adminhtml/templates/hello.phtml&lt;/h3&gt;

&lt;p&gt;Create your template file, add some content and you will see it magically appear within the content of your admin page.&lt;/p&gt;

&lt;p&gt;I’m pretty sure you’re XML-ed out by now so I’ll leave this tutorial here, thanks for reading!&lt;/p&gt;
</description>
        <pubDate>Wed, 16 Mar 2016 14:00:00 +0000</pubDate>
        <link>http://adammoss.co.uk/magentofox/magento-2-basics-part-5-creating-an-admin-page/</link>
        <guid isPermaLink="true">http://adammoss.co.uk/magentofox/magento-2-basics-part-5-creating-an-admin-page/</guid>
        
        
        <category>magento2</category>
        
        <category>magento</category>
        
      </item>
    
  </channel>
</rss>
