Blog

Introduce YML Linting to your JSS Apps

Intro: This post shares how and why you might like to introduce a YML linter into the build process for your next Sitecore JSS project. Particularly if you are relying on the YML import process when building a new application. Shout out to David Huby (Solutions Architect) for introducing team Aceik to yaml-lint.

Why would you want to do this on a JSS project?

When running the JSS application and testing latest changes, we sometimes discovered some strange behaviour with dictionary items, or a page might not load properly.

A 404 page displayed after an invalid YML change was made

This can be caused by a small (incorrect) change in YML breaking individual routes. For example, lets say you have an incorrect tab or character in the wrong place. The YML syntax requires correct spacing and line returns to be valid but this is not always so obvious when done incorrectly. Sometimes only after you run the JSS application and test out the changes do you discover some strange behaviours or the page not loading properly.

To avoid this we found it handy to introduce a YML linter into the JSS build process. This solves the issue of someone making a small change to the YML files and breaking individual routes.

Here are the steps needed to introduce a YML linter into a node-based JSS project:

  1. Install yaml-lint (https://www.npmjs.com/package/yaml-lint)
  2. In the application root create the file .yaml-lint.json
  3. Update the package.json
    • Create a new script entry called yamllint
      • “yamllint”: “node ./scripts/yaml-lint.js”
    • Update the script called ‘build’
      • “build”: “npm-run-all yamllint –serial bootstrap:connected build:client build:server”,
  4. Download the following scripts file and place it in the /scripts folder
    1. https://github.com/TomTyack/jss/blob/feature/YAML-Linter/samples/react/scripts/yaml-lint.js

You can also see the pull request with the above changes at:

https://github.com/Sitecore/jss/pull/385/files

Demo

People of Aceik: Jen Gorshkova, Account Manager

We have launched a new series to introduce you to our talented and hard working team mates. They’re behind the success of our client’s projects – working diligently to ensure we exceed our customers’ expectations.

This month, we sat down with our Account Manager, Jen Gorshkova.

Jen, tell us about your background.

Jen: I moved to Melbourne in 2014 when I started my career in business development at Epicor, ERP software solution. I fell in love with helping clients by finding the best solutions for the business. Getting the “Aha” moment from my clients after the implementation was the most rewarding, and seeing their business succeeding and growing further.

In 2016, I joined Revolution IT as an Account Manager, where my role was to build and maintain strong, long-lasting customer relationships with the clients and partners. I was working closely with the Product Owner and Marketing Manager to push out a new product – Crowdsource testing. The new and most effective method of digital testing platforms.

In 2018, I joined Aceik as an Account Manager to look after our exciting clients and ensure world-class delivery.

Tell us about joining Aceik

Jen: I met Jason, our CEO, in 2018 because he had an account manager role available. I joined Aceik because Jason wanted to build a company that is different from any other. The company that deeply cares about the quality of the work delivery, and ensures honesty and transparency with their clients.

At that time, Aceik was at the start of its growth journey. Jason had won a few large clients and projects and required help to provide the best service! I was looking forward to bringing my expertise and experience working with enterprise clients to help take Aceik to the next level. I was learning new skills and taking on responsibilities outside of my role from the day one. It was also great to see how close the Sitecore community is.

Why did you join Aceik?

Jen: I was impressed by Jason’s vision of wanting to build a unique company. A company that is known for providing high-quality work, full transparency and honesty with its clients. I wanted to be part of a team that doesn’t cut corners, always thrives and offers learning and improvement opportunities.

I got really excited about contributing to the success and growth of Aceik. My work ethic always included providing the best possible solution to my clients, and ensuring that they are happy with the outcome. The Aceik culture is very much aligned to how I operate.

I was also thrilled with the line of work, as Aceik provides a great range of digital services from a full rebuild to solution review to ongoing support. Aceik stood out from most companies out there, and I knew that my skill set and can-do attitude would benefit the team and company.

What’s your favourite thing about working for Jason and with the team?

Jen: I like working in a close-knit team where each day is different and never boring. You always have to wear different hats, and take on extra responsibility, learn a new skill set and see new ideas come to life. I have participated in various roles – marketing, project management and operations. Sometimes, I’ve even been challenged to improve my technical knowledge and skills. I have learnt a lot and I’m grateful to have the best teachers!

The team at Aceik is always keen to jump in and help. No job is too small or too big. Each team member is unique and has their own style of working – but one thing everyone has in common is their passion for what they do.

Working in a culture where each opinion matters is how we do it at Aceik!  

Is there a project, a customer campaign, something that stands out in your mind that you were really excited that you got to tick that box and go, “This is done”.

Jen: One of our clients reached out to us, as they had a tight deadline to meet. The previous vendor had left the platform in non-working state. We were able to quickly to jump onboard and identify their issues and put the best plan forward on rescuing the project.

It was amazing to see two teams collaborating and brainstorming ideas. It was a great representation of a truly agile project! Where we had the scope right from the start but also the opportunity to add and change features along the way.

The client was pleased about the open communication via Slack and seeing tickets moving through the board on JIRA – where they could easily comment as we go. One of their favourite parts was the showcase at the end of each sprint, where we all celebrated success!

When the customer went live – their site speed was drastically enhanced, user experience improved and they won new clients! Here at Aceik we see our clients’ success is our success!

While we’re in the middle of coronavirus pandemic and Aceik is now working from home. How do you make it work for you?

Jen: As a company, we ensured everyone is comfortable and have all they need to work from home. My working station is well set up with an ergonomic chair and a big screen. We also introduced regular online catch-ups and quick quizzes/games to keep the team connected.

I do miss meeting up with the team in person, but thanks to technologies such as Slack and Zoom, we’re still able to communicate well and ensure our projects are delivered on time.

There a few tricks I have learned about working from home:

  1. Prioritise your tasks in the morning and ensure to timebox them.
  2. I also found it important to disengage and go for walks around lunchtime. It meant I was refreshed and energised for the afternoon.

Let’s talk about life outside of Aceik. Who is Jen outside of work?

Jen: I’ve moved countries a few times now. I was born and raised in a place called Kyrgyzstan, which is a beautiful country in the middle east. When I was younger, I moved to New Zealand, but always wanted to live in a big city and eventually relocated to Melbourne, one of the most liveable places in the world.

Being active is a big part of my life. I enjoy running, yoga, hikes and healthy eating. I believe that staying healthy helps with being productive at work. I also believe in continued learning. Since joining Aceik, I’ve become certificated in a number of Sitecore courses. And my current goal is to gain new project management skills and some of the courses I would like to do:

  1. Prince2
  2. PMBok

One Performance Blog to Rule them all – Combining the 6 Pillars of Speed

I have done a number of posts and talks at user groups on Page Speed and performance over the last few years. I have split the various topics into individual blog posts for the most part as performance is dependent on many factors. What has really been missing is a complete demo of how all the different techniques come together to give your site a really good score. So that’s what I intend to demo here is the combination of the 6 pillars of page speed in one Sitecore instance. To recap here are the 6 pillars of page speed performance in my opinion:

1) Introduce image lazy loading

2) Ensure a cache strategy is in place and verify its working. (must have adequately sized production servers)

3) Deploy image compression techniques

4) Use responsive images (must serve up smaller images sizes for mobile)

5) Introduce Critical CSS and deferred CSS files

6) Javascript is not a page speed friend. Defer Defer Defer

I have shown a subset of these previously but crucially three critical pillars to do with imaging were hard to achieve at the time. This is now possible due to being able to support Next Gen image compression (webp), which I wrote about in my previous blog. With a little more time and investigation Image Lazy Loading, responsiveness and image compression to give a more complete picture of how each pillar impacts page speed.

Here are the tools and blogs I will use to achieve each of these:

1) Image Lazy Loading – Blog post by MVP Sitecore SAM and https://github.com/thinker3197/progressively

2) SXA Cache Settings – SXA official documentation

3) Next Image (WEBP) Image Compression – https://github.com/Aceik/ImageCompression

4) SXA Responsive Images – SXA official documentation

5) Introduce Critical CSS and deferred CSS files – https://github.com/Aceik/Sitecore-Speedy

6) Javascript is not a page speed friend. Defer Defer Defer – https://github.com/Aceik/Sitecore-Speedy

Alternatives: Mark Gibbons (MVP) recently upgraded the Dianoga image library to support WEBP. Worth a look if you don’t want to use a third party API. It also supports a CDN. Also Vincent Lui (MVP) also pointed out in his recent SUGCON talk, you can achieve both image compression and image lazy loading via some of the modern CDN’s. That is a great (easy) option if you are retro fitting these techniques to a live website.

I’m not going to dive deep into exactly how to setup each of these things as I think the individual links have sufficient instructions. I will show in the Demo videos how each pillar impacts the HTML rendered. For the most part I am keen to demonstrate the impact of each of these line items and how each one will benefit your page speed score.

Before we begin its important to understand that the algorithm (Lighthouse) behind Google’s Page Speed insight doesn’t work in an exactly linear fashion. If you improve your score by ticking off one of the above, don’t expect ticking off another issue will have the same benefit. The last 20 points out of 100 (on the mobile scoring system) is that hardest to achieve based on what I have seen.

Live Demo Video Series that accompanies this blog:


Test Outline:

Google Page Speed Insights — Scores can fluctuate widely based on network latency. At time you will experience score fluctuations at different times of the day on the same site.

In general this is a guide

Here is the general outline of the VM that hosted the IIS instance for testing. I also put the VM under some basic load while running the tests.

  • All the test below used Sitecore 9.3 and the SXA habitat example site.
  • Test used the live Google Page Speed insights tool via the url: https://developers.google.com/speed/pagespeed/insights/
  • Sitecore was setup on an Azure VM with the specifications:undefined
  • The test was run 5 times, to get an average score.
  • The test page was the homepage of the Habitat site and the page was requested before running the test 5 times so that the instance could be considered warm.
  • EXM and XDB were not running on these test instances.
  • Test results are Mobile Page Speed scores only – This is the most important metric in today environment and good desktop scores are not really a challenge.
  • The default Habitat cache rendering for Navigation was left on for all tests. (without this the site fails under basic load altogether)
  • All tests were conducted under load in an attempt to replicate a production environment. For this I used a node package called loadtest.
  • SXA CSS/Javascript optimisations were turned on, but as I have mentioned before this has a minimal performance boost.

loadtest -c 10 –rps 10 http://baselinecd.dev.local/

10 requests per second with a concurrency of 10

Baseline Score

The Baseline score encompasses the habitat site installed with no modifications.

Result: 48 / 38 / 40 / 34 / 38 = 39.6/100 Average

Observation: Heavily penalised for CSS and Javscript loading times.


Image Lazy Loading

All images on the homepage were converted to be Lazily loaded. A single large blurred image was used as the placeholder for all images.

Result: 57 / 55 / 61 / 52 / 63 = 57.6/100 Average

Observation: Around the mid point of the scale, image lazy loading has around a 15 – 20 point impact.


Rendering Cache Strategy

I have blogged extensively about this in the past but setting up cache settings properly is so critical and has a major impact. Its also one of the easiest things to fix for a poorly performing Sitecore site. Also note the only way to accurately demonstrate the impact that Rendering cache has on a site is to test it under load.

This test was run with higher user per second: loadtest -c 10 –rps 30 http://baselinecd.dev.local/

With Cache Enabled:

49 / 56 / 41 / 54 / 54 = 50.8

Without Cache Enabled:

ERR_TIMED_OUT / ERR_TIMED_OUT / ERR_TIMED_OUT / ERR_TIMED_OUT / ERR_TIMED_OUT = You get the point 🙂

Observation: Rendering cache settings are critical and should be the first step in Page Load Speed refinement for a Sitecore site. 10 Point benefit observed once a site is stable under load.


Image Compression

Result: 60 / 58 / 61 / 62 / 62 = 60.6/100 Average

Observation: Around the mid point of the scale, image lazy loading has around a 20 point impact.


Critical CSS

Result: 74 / 78 / 79 / 81 / 81 = 78.6/100 Average

Observation: The combination of critical CSS in the head and Deferred styles provides a meaningful page speed boost. 25 Point observed benefit.


Deferred Javascript

Result: 92 / 94 / 93 / 94 / 94 = 93.4/100 Average

Observation: Javascript has a massive impact, reducing it drastically in the initial payload provides massive page speed improvements. 40 Point observed benefit.

You might think, hey I will just do Deferred Javascript and it will be all good. While this particular PIllar/Criteria does have the biggest impact. Every site is different and as mentioned earlier scores fluctuate. The upper part of the scoring system is the hardest to reach. So while this is a great starting point, ignore the other speed pillars at your peril.


Responsive Images

Result: 56 / 54 / 59 / 56 / 60 = 57/100 Average

Observation: Around the mid point of the scale converting images to be responsive (srcset support) has about a 10 point impact.


Results Summary

CriteriaAverage ScoreObserved Benefit
No Change (SXA Habitat Home OOTB)41.8 / 100
Image Lazy Loading57.6 / 10015 Points
Sitecore Rendering/HTML Cache Settings50.8 / 10010 Points
Image Compression (webp)60.6 / 10020 Points
Critical CSS78.6 / 10025 Points
Deferred Javascript93.4 / 10040 Points
Responsive Images57 / 10010 Points

The Pillars Combined

In isolation we can see the rough results of what each of the pillars might do to our Page Speed. The real question is what does combining all these pillars produce.

Result: 100 / 100 / 100 / 100 / 100 = 100/100 Average

Observation: Do I expect this on an actual production site realistically ? That is certainly the dream, but in reality you should be over the moon if you make it into the 90s and pat your self on the back if you get into the 80s as well. For any Sitecore site if you make it into the 90’s for mobile, your doing an amazing job.

Admittedly for the combined demo I skipped the responsive image pillar. SXA supports Responsive Images but not in combination with data attributes. It was going to be a bunch of work to write a custom SXA handler to support both lazy loading and responsiveness at the same time. That is not to say its not possible. Either way the impact was minimal.

Conclusion

Page speed is so critical to SEO and visitor conversion. A slow site instantly turns away users on mobile and tablet devices. Admittedly the final result shown above and in the video have required that all the right tools be available to the Sitecore community. Which up until recently you likely needed to bake your own solutions in order to get that over the line.

I think its now becoming possible to aim fairly high (90/100 on mobile) with our Page Speed scores, but it does require getting most if not all of the Architecture Pillars above working together. Its worth learning each of these and understanding the pitfalls and limitations if you want really great page speed. Good luck and feel free to get in touch with any questions.

Footnote

The combined pillars can produce great results but you still need to load test before going live. Checkout the video below where I search for the breaking point using the loadtest tool. Please note that this node based load test tool should just be used for a guide. Before go live I recommend using a hosted load tool solution that has multiple geographic locations. Tests done based on one network location or device will result in a network bottle neck and give you false positives.

Bonus Video: https://www.youtube.com/watch?v=96YcxyhYh0U

Unicorn & Sitecore with custom rule configurations

Unicorn is one of the most widely used utilities for syncing Sitecore item changes between different environments. Sitecore 9 has introduced rule based configuration that is used to target configurations for different roles (ContentManagement, ContentDelivery etc..). We can also create custom rules by registering them in web.config.

This post will walk you through the use of custom rules to optimise Unicorn for development and deployment.

Environment rule configuration

Create a custom env rule by registering the below in web.config. This can then be used to target the configurations to be enabled/disabled based on the environment.

<appsettings> 
...
<!-- Possible values Development, Test, UAT, Production -->
<add key="env:define" value="Development" />    
... 
</appsettings>

Default Helix configuration uses serialization as the root folder within each module at the respective helix layer. You can also make different unicorn configurations to go to different folders by configuring the targetDatastore for that configuration.

<targetDataStore physicalRootPath="$(sourceFolder)\$(layer)\$(module)\serialization-once" />
Use this to target the configurations to write to serialization-once folder

<targetDataStore physicalRootPath="$(sourceFolder)\$(layer)\$(module)\serialization-dev" />
Use this to target the configurations to write to serialization-dev folder

The above configurations help differentiate the items that are serialized and synchronized only once and to be only synchronized on developer environments.

Sample Configuration for Developer Content Serialization

<configuration 
name="Project.Website.Serialization-dev"
description="Project Website Dev Unicorn items"
dependencies="Project.Website"
extends="Helix.Base"
env:require="Development">
<targetDataStore
physicalRootPath="$(sourceFolder)\$(layer)\$(module)\serialization-dev" />
<predicate
type="Unicorn.Predicates.SerializationPresetPredicate, Unicorn"
singleInstance="true">
<include
name="Dev.Content"
database="master"
path="/sitecore/content/<site>/<devcontent>" />
</predicate>
</configuration>

Sample Configuration for New Items Only Serialization

This configuration becomes always update on developer environments.
<configuration 
name="Project.Website.Serialization-Once"
description="Project Website new items only"
dependencies="Foundation.*,Feature.*,Project.Core"
extends="Helix.Base">
<evaluator
type="Unicorn.Evaluators.NewItemOnlyEvaluator, Unicorn"
singleInstance="true"
env:require="!Development"/>
<!-- This will be New Items Only in All environments except Development -->
<targetDataStore
physicalRootPath="$(sourceFolder)\$(layer)\$(module)\serialization-once" />
<predicate
type="Unicorn.Predicates.SerializationPresetPredicate, Unicorn"
singleInstance="true">
<include
name="Project.Content.Newitems"
database="master"
path="/sitecore/content/<site>/<new-items>" />
</predicate>
</configuration>

Unicorn rule configuration

A custom unicorn rule can be created by registering the below in web.config. This can then be used to apply configurations based on if unicorn is enable/disabled.

<appsettings> 
...
<!-- Possible values On, Off -->
<add key="unicorn:define" value="On" />
... 
</appsettings>

Having unicorn enabled in non development environments can impede the authoring quality of life especially when using Azure PaaS where the disk I/O is not that great. As part of the CI/CD once the unicorn sync has been performed we can disable unicorn using the following patch config. This config only works when unicorn rule is set to Off.

<configuration 
xmlns:patch="http://www.sitecore.net/xmlconfig/"
xmlns:role="http://www.sitecore.net/xmlconfig/role/"
xmlns:unicorn="http://www.sitecore.net/xmlconfig/unicorn/">
<sitecore
unicorn:require="Off"
role:require="ContentManagement Or Standalone">
<unicorn>
<configurations>
<patch:delete />
</configurations>
</unicorn>
</sitecore>
</configuration>

As part of the the deployment pipeline have a step to change the web.config unicorn:define value to Off so this above patch will take into effect.

Next Gen Image Compression in Sitecore

Spoiler: This post is not a post about Dianoga, I take a deep dive into Tiny PNG and Kraken.IO integrations into Sitecore. The results are worth checking out at the bottom.


At the start of the year, I’ve picked up where I left off, on page speed. Last year I took a deep dive into attempting to improve the page speed on Sitecore SXA sites by using some of Google’s recommended techniques to structure the page. If you haven’t already seen it, head on over the Sitecore Speedy and see some of the results we achieved.

I’ll be the first to admit that getting really good page speed scores isn’t easy. It takes a lot of different factors to come together. Just as a reminder, here is the main list that I would consider you need to check off to be winning at this game.

1) Introduce image lazy loading

2) Ensure a cache strategy is in place and verify its working.

3) Dianoga is your friend for image compression

4) Use responsive images (must serve up smaller images sizes for mobile)

5) Introduce Critical CSS and deferred CSS files

6) Javascript is not a page speed friend. Defer Defer Defer

For this post, i’m going to look at an alternative to Dianoga. I’m a big fan of Dianoga and have used it over the years to crunch loads of oversized images introduced by Content Editors. I will, however, say that it can add complexity to deployments and CI/CD pipelines and while some claim to have had success in Azure Apps, others have not.

On the flip side, content editors love Tiny PNG, which is one of the most popular image compression website utilities going around. Tiny PNG also has a developer API, so we have used this to build in a compression tool that can be used directly from your Sitecore toolbar.

The button below is hooked up to chat to Tiny PNG API. It will send across your image data and receive a compressed image back for storage.


Full disclosure, I’m not the first person to hook up Tiny PNG to the image library. I could find two other implementations

One will allow you to run a powershell script to connect to the Tiny PNG API and the other is a module to connect to the API on upload.


This implementation of the Tiny PNG API introduces the following variances:

  • A button in the CMS to crunch any single image.
  • A scheduled task that will process any image not already processed.
  • Error handling for when the API limits are reached
  • Logging that outlines which images were processed.
  • Before and After compression information stored in any Image field of choice.
  • A feature toggle to turn the whole feature on/off

All the source code is available at: https://github.com/Aceik/ImageCompression

Now let’s jump in have a look at the results just from crunching a few images down:

Without image compression:

Click to Enlarge Image

To compress the images on the page, we head on over to the “Compress” button in the Media tab that we have introduced.

Click to enlarge

A few examples of compression results taken from homepage images:

Before: 158.4 KB | After: 110.6 KB

Before: 197.8 KB | After: 135.3 KB

Before: 640.0 KB | After: 120.7 KB

After compressing all the images on the page the saving can be seen below.

Click to enlarge

So our total image size saving is 2.4MB – 1.3MB = 1.1MB

A pretty decent saving from just pressing the compress button on 27 homepage images. Also, consider that the user won’t notice any difference in image quality as this method uses lossless compression.


The compression achieved is great for helping us tick off one of the requirements for fast pages with Google. But as we are about to find out Google will likely still complain about two other criteria. When it comes to Google Page Speed insights a page that does not have properly processed images will bring up the following three recommendations:

Here is a break down of how we address each one:

  1. Serve image in next-gen formats – Image formats like JPEG 2000, JPEG XR, and WebP often provide better compression than PNG or JPEG, which means faster downloads and less data consumption. Learn more.
  2. Properly Size images – Your CSS layouts should be responsive and use modern image retrieval techniques that adapt the image size requested based on screen size. Read More
  3. Efficiently encode images – The Tiny PNG integration above will take care of this. This is all about compressing the image to as small as it can get without a visible loss of quality.

So assuming you have already achieved number three using the Tiny PNG integration or another source, let us look at how we can solve the next-gen image requirement.

As a quick side note the testing I did after converting the images to next-gen also ticked item number two above. I don't think this should be relied on however and its best to incorporate responsive images into your projects from the beginning.  

When looking into how to convert images to a next-gen format I opted to target webp. Google has a nice little page explaining the format here.

WebP is natively supported in Google Chrome, Firefox, Edge, the Opera browser, and by many other tools and software libraries.

Once again I opted to look for an API that would provide the conversion for me so that Sitecore could easily connect, send the image and then store the result. All without any extra hosting requirements. I opted to go with Kraken.IO image APIs as they have a free 100MB trial offer and well free is a good price when building proof of concepts. The integration is all available on Aceik’s github repository. Just signup for your own API keys add them to the module settings (in the CMS) and start converting.

To test out just how much this would impact the image payload size for the whole page, I once again converted all the images on the SXA habitat homepage.

Here are the results:

Click to enlarge

So our total image size saving is now 2.4MB – 0.79MB = 1.61MB

The reduction in size from a non-compressed image to a webp formatted image is truly impressive.

A few examples:


Conclusion

I can only conclude by saying that if page speed is really an important factor for your Sitecore project take a look at Tiny PNG. If you want to go next level with your image formats and achieve great compression try out the Kraken.IO API integration as it could be well worth the small subscription fee.


Results

CompressionTotal Image SizeSaving
None2.4 MB
Tiny PNG1.3 MB1.1MB
Kraken.IO (webp)0.79MB1.61MB

Notes:

The module and code mentioned in this blog post are available on Aceik’s Github account. This also contains installations instructions.

GitHub: https://github.com/Aceik/ImageCompression

After installation, your content editors will simply be able to compress and convert images as needed from within the CMS.

Click to enlarge

The Github Readme contains a run down and the standard settings inside Sitecore as shown below:

Aceik hires Brad Paton as Account Director

Exceeding our clients’ expectations has always been and continues to be Aceik’s #1 priority. With the current difficult climate, we are doubling our efforts to look after our clients. To this end, we’re excited to announce that our team has grown again with the addition of Account Director, Brad Paton. Welcome Brad!

Brad’s expertise in digital strategy development and execution as well as his understanding of the Sitecore platform will go a long way to helping our clients to achieve their business goals. We’re also thrilled to share that with Brad now on-board, we’ll be offering Aceik’s Sitecore Business Optimisation Services (Aceik SBOS) to our marketing clients.

We sat down with Brad to get to know him a little better. Here’s what he revealed about himself.

Tell us a little bit about yourself.

Brad: My career has been an interesting one when it comes to digital software development in that I actually studied law many, many years ago. It was the late 90’s, the internet was taking off and I found myself interested in computers and technology. I taught myself to code– first Microsoft BASIC, then Visual Basic, and when the internet gained traction learned HTML, and eventually JavaScript.

I was a big Essendon Bombers Football fan. I actually sent them a letter and said, “I think this internet thing is going to be pretty big do you want to get involved?” and I helped them create the first official Essendon website.

But then I finished my Arts/Law degree and worked as a lawyer for a few years before deciding that law wasn’t for me. I really liked building websites. So, I returned to the Essendon guys and kept working with them, and then also after that build up my own small web design business in the 2000s.

Following the sale of my business to IMG, I landed at Reactive, a digital agency with a Sitecore arm that was eventually sold to Accenture. I spent 4 years working for Reactive and another 2 years at Accenture.

It happened that Richmond Football Club was looking for a Head of Digital so I made the leap from one football team to another. I didn’t think I could change teams from Essendon to Richmond but turns out you can. And so, I’ve spent the last four years as Head of Digital at Richmond, in which time the digital part of the business has grown enormously. We doubled headcount from six to 12 in those four years and won two premierships.

I was introduced to Jason Horne, our Managing Director, by Reactive’s former co-founder. Jason was looking for someone to manage digital strategy, business development and client relationship management. That ticked all of the boxes of what I was looking for in my next role. I started last Friday, met Jason at the office, had a client meeting, collected my computer and have been working remotely ever since.

You’ve been working in digital for about 20 years now. What do you love about digital?

Brad: The thing that kept me in it for so long is that it just changes all the time. So, in my time with Essendon FC back in the 2000s, it went from being a static website to a content managed website. Then we added video and we were the first AFL club to do that. Then social media came along, and then the iPhone was released in 2007. With mobile being important, we built an app.

Digital is just constantly evolving, and you never know what’s going to pop up on the horizon that needs to be addressed. I like the changing nature of the industry.

Any predictions on what’s coming in the next 12 months or so?

Brad: I’m huge on voice. I’ve got a three-year-old daughter and if she ever uses a keyboard, I’ll be surprised. We’ve got a Google Home at home and she can control that already. But voice taking over inputs from keyboards, visual pointing and interactions so whether that’s just by hand gestures or mouse or whatever.

But then of course, the next big leap is going to be augmented reality and virtual reality and how that impacts life. It has promised a lot for a long time and it hasn’t delivered, but the technology now is a lot better and cheaper. They’re starting to scale and I think for the next five to 10 years VR is going to really start to take off and who knows what that means for society.

We’re pretty much in lockdown for the coronavirus at the moment. It doesn’t matter if it’s virtual or physical anymore. If you’re in the same room physically together, you can be there virtually just as easily, and people are doing that at the moment. They’re having a Google Hangout or Skype, if they’re in self-isolation to try and maintain that human contact. And as the technology progresses, then virtual reality is that next logical step.

Why did you choose to join Aceik then?

Brad: Just from the position description I was interested, but when I met Jason, I got a really good sense of his vision and purpose for Aceik. He wants to grow the business in a sustainable way to retain quality. And that’s pretty rare in a lot of businesses because they just want to scale quickly. And what happens then is you might do some good work early, you get a lot more business, you hire a lot of people, not necessarily the most qualified people, and then you turn out work that’s not as good and your reputation goes down. So, I like Jason’s philosophy.

And I guess the other thing is that I like the idea of getting involved in a business that is more technically focused and keeping up to date with the latest trends in that area.

And funnily enough, I learned only after I’d met with Jason that Lila Tournier, who I worked well with at Reactive for about three or four years is currently at Aceik. So, once I knew she was there that was kind of like almost the last check in the box to say, “Yes, obviously this is an organisation worth working for.”

What are your goals over the next couple of months?

Brad: The first thing is really to identify the opportunities, especially in this climate that we want to prioritise. I want to help in terms of growing those relationships with existing clients to ensure that when new opportunities come up we’re first on the list to be looked at. And then second to that is looking at what new opportunities exist with potential organisations that haven’t been clients.

Another the big opportunity is around digital strategy. So, rather than just delivering excellent  technical work, which Aceik has an amazing reputation for, we can actually go in before that technical phase, and do a digital strategy piece of work with the client. This would involve workshops, customer journey mapping and coming up with recommendations on how to use the Sitecore platform to the best of its ability. We all know Sitecore, at its core can just be a content management system for a website, but if you want to get to the top you need to use the marketing features and the marketing features are where the ROI is.

We’re already looking at how we put together multiple options for clients to engage us in a digital strategy piece of work, with the outcome being a roadmap the best way to implement Sitecore.

Was there anything else you wanted to add?

I’ve seen a lot of change in the industry over the last two decades. I remember having my first modem and I had to tell my parents they couldn’t use the phone for two hours because I needed to get onto the internet and learn how to code. Whereas now, I look at my Apple watch on my wrist and it can tell me almost anything that I need to know.

And with that experience, I’ve learnt that times change very quickly. Don’t plan on putting something together today for an activity in 12 months because it’s unlikely to be the same then. It’s crucial to be adaptable.

COVID-19 update: It’s all business as usual at Aceik

Aceik’s approach to the COVID-19 outbreak and how we will continue to support our clients, team, families and community throughout this difficult period.

Remote working is our norm

For many companies, remote working isn’t part of their normal practice. In the last few days, employers and HR departments are frantically exploring and launching flexible work options which have a level of complexity for traditional workplaces. It has provided a new level of chaos and complexity to their work processes and relationships.

Not for the Aceik team.

We have always offered our employees the option of flexible working. In fact, what many of our clients and community may not realise is that 95% of our work has traditionally been remote. Yes! Our engagements with RAA, Fitness Lifestyle Group, Fitness First, Goodlife Health Clubs, Village Theme Parks and Chisholm Institute (to name a few) have all been undertaken offsite.

What has changed for Aceik

The health and safety of the team is paramount and so to complement our flexible working culture, we’ve implemented a policy specifically addressing the changing COVID 19 situation. As of Friday 13 March 2020, all team members are working remotely. There is no international travel and domestic travel is only if completely unavoidable. In-person meetings and events are limited. Our phone system has been diverted and will continue to be answered.

Aceik has always offered online training for developers, marketers and clients. We have moved all of our in-person Sitecore public classes to online training for the foreseeable future. Aceik’s Virtual Classroom will be delivered via Google Hangouts and will feature the same live instructor interaction, the same materials and remote machine lab exercises as you would have in our face-to-face courses.

As always, Aceik documents as we work, and this process is unchanged. This means that if a member of our team becomes unwell, that another colleague can easily step in. It is vital to us that there is no interruption to our clients’ businesses and projects.

Tips for anyone new to remote working

We asked the team to share their top tip for remote working:

1. Continue with your regular morning routine just as if you had to commute to work and play music in the background (recommendation: Bossa Nova does the trick).

2. If you can have a separate space that is only used for work (for example, a study, spare bedroom etc) to commute to work, then it will help family to understand that you are at work and not home.

3. Make a checklist in the morning and use the Pomodoro Technique to execute. There are plenty of phone apps available to manage the technique, and act as a timer.

4. The number one rule for client work is keeping the progress updates going on whatever communication platform is used. So, if its Slack keep the updates streaming in because this builds and maintains trust between all parties.

  • Check in at the start of the day with your team and client.
  • Update them when you complete a task.
  • Update them when you’re blocked on a task.

5. Your new colleagues might now have fur and four legs. It is awesome working alongside the furbabies but when you have a call scheduled, ensure you’re in a quiet space. Not everyone understands how offensive the dogs find it that the pesky postman keeps coming back day after day (that guy just hasn’t learned!)

6. Get outdoors for a walk around lunch time.

7. Take short breaks like you would in an office. It’s just that this break might look like putting on a load of washing, hanging clothes, emptying the dishwasher or weeding. But always return to your laptop (and not the TV) once you’re done.

8. Set an alarm to get up, move around and take a few steps. It’s important to stretch and keep moving every hour. Getting the heart rate up every now and again keeps you alert, and some stretching will help prevent long term injury. You could even do a minute or two of core work like planks or push ups.

9. Staying connected as a team is super important. Start a Slack channel like we have called #coffee_buddies channel for random virtual coffee catch ups. And encourage staff to share ideas to help work and socialise like a dream! 

10. Prepare some witty one liners for when your kids add their own commentary or make an appearance during your video meetings. 

We’re committed to…

Nothing has changed for Aceik in terms of our commitment to our clients, team, suppliers or community. We continue to be committed to:

  • Respecting our client relationships and always exceeding expectations.
  • Paying our suppliers on time or ahead of time so there is no disruption to their business activities.
  • Remunerating our team members on time and recognising their continued outstanding work.
  • Doing our utmost for our community during this difficult time
  • Slowing the spread of COVID 19

Accessing the JSS Dictionary in C#

This is a quick post to guide developers through gaining access to the JSS Dictionary in the backend C# code.

Why would you want to be able to do this?

The reason we originally had to do this was that our JSS Angular application had editable content from the dictionary that we also wanted to access in C#. In our particular case, it was to inject the content into an email template that would be sent to the user. To save duplicating content it made sense for both the front end and C# to have access to the same dictionary.

Where do we start?

The following assumes you have a Sitecore instance with JSS installed and a JSS application you are working on. Grab your favourite de-compilation tool (I use ILSpy) and locate the following DLL in the bin folder of your running Sitecore instance:

Sitecore.JavaScriptServices.Globalization.dll

Once you have that open in ILSpy you want to have a search for DictionaryServiceController

public class DictionaryServiceController : ApiController

The following method is what we want to use in our C# code:

public DictionaryServiceResult GetDictionary(string appName, string language)

It takes the unique application name (that belongs to your application) and the language (“en”) as a parameter. As a result, you will get back a dictionary object that you can use to lookup up your content.

This is the Controller that would normally be called via an API on the front end. So how do we call it from normal C# service for instance?

Firstly, the controller has a constructor that has three parameters that are injected via DI (Dependency Injection).

IConfigurationResolver configurationResolver, 
BaseLanguageManager languageManager, 
IApplicationDictionaryReader appDictionaryReader

Using ILSpy once again you can find that the above three parameters are all set up in the DI container via RegisterDependencies.cs in various JSS assemblies. The Controller itself is already registered in the DI Container as well, which is very handy.

If you have a look at showconfig.aspx in the admin tools you can see that a lot of the dependencies are registered via RegisterDependencies.cs

For example:

<configurator type="Sitecore.JavaScriptServices.AppServices.RegisterDependencies, Sitecore.JavaScriptServices.AppServices" patch:source="Sitecore.JavaScriptServices.AppServices.config"/>

Dependency injection is a whole other topic so I will leave that to your personal preference as to how you achieve it. For the purposes of the following complete code example, I have used the Services Attribute style setup. If you want to keep consistency with Sitecore you could also setup via the RegisterDependencies.cs class of your own and use a patch file to kick it off.


Example Service:

using Sitecore.Foundation.DependencyInjection; // Borrowed from habitat
using Sitecore.Diagnostics;
using Sitecore.JavaScriptServices.Globalization.Controllers;

namespace Sitecore.Foundation.JSS.Services
{
    public interface ITranslationService
    {
        string TranslateKey(string key);
    }

    [Service(typeof(ITranslationService), Lifetime = Lifetime.Transient)] 
    public class TranslationService : ITranslationService
    {
        private readonly DictionaryServiceController _controller;
        
        public TranslationService(DictionaryServiceController controller)
        {
            this._controller = controller;
        }

        public string TranslateKey(string key)
        {
            var dictionary = GetDictionary();
            if (dictionary.phrases.ContainsKey(key))
                return dictionary.phrases[key];
            Log.Error("Dictionary key {key} not found", this);
            return string.Empty;
        }

        private DictionaryServiceResult GetDictionary(string appName = "myAppName", string language = "en")
        {
           return _controller.GetDictionary(appName, "en");
        }
    }
}

Above is a simple service that can be used from just about anywhere in your C# code.

Simply change the appName and language as required to access the correct JSS dictionary. Also, remember to publish your app dictionary to the web database or you may get no results.


There we have it, accessing the JSS dictionary from C# in a nutshell. I hope this helps some other folks get this done quickly on JSS builds.

An Introduction to Sitecore Pipelines

What is a Sitecore Pipeline?

In Sitecore pipelines describe a series of discrete steps that are taken to achieve some objective.  If you think about writing code to handle an HTTP request for example you could create a monolithic class that does the job from end to end; however the pipeline approach is a number of classes that can be invoked in order.  First do this and then do that etc. 

There are many Pipelines in Sitecore.  You can view existing pipelines and the processors that they call using Sitecore Rocks in Visual Studio.  Right click on the site connection and choose Manage. Click on the Pipelines tab in the Visual Studio edit pane.  Click on one of the listed pipelines to see all the processors that are executed as part of the pipeline.  There are pipelines with a single processor at one end of the scale to the httpRequestBegin pipeline with 45 distinct steps at the other.

Why are they useful?

Thinking about the monolithic class above it would be very difficult to maintain or modify, It would also be truly massive.  So modularising it would make it much easier to maintain. 

It also makes it much easier to customise.  For example, if we consider a pipeline that has three processors it might be drawn something like

To add to the existing functionality we could include a new step like

Where we add some custom function after Step 1 and before Step 2. 

We could also replace an existing step completely

How are they defined?

Pipelines are defined using XML in sitecore.config.  In the example below we can see the httpRequestEnd pipeline definition.  The three processors are called in the order in which they are listed.  A parameters object is passed between them to provide continuity.  The final processor is also receiving four additional parameters from the config file.

<?xml version="1.0" encoding="utf-8"?>
<sitecore database="SqlServer" xmlns:patch="http://www.sitecore.net/xmlconfig/" xmlns:role="http://www.sitecore.net/xmlconfig/role/" xmlns:security="http://www.sitecore.net/xmlconfig/security/">
…
<pipelines>   
… 
<httpRequestEnd>
      <processor type="Sitecore.Pipelines.PreprocessRequest.CheckIgnoreFlag, Sitecore.Kernel" />
      <processor type="Sitecore.Pipelines.HttpRequest.EndDiagnostics, Sitecore.Kernel" role:require="Standalone or ContentManagement" />
      <!--<processor type="Sitecore.Pipelines.HttpRequest.ResizePicture, Sitecore.Kernel"/>-->
      <processor type="Sitecore.Pipelines.HttpRequest.StopMeasurements, Sitecore.Kernel">
        <ShowThresholdWarnings>false</ShowThresholdWarnings>
        <TimingThreshold desc="Milliseconds">1000</TimingThreshold>
        <ItemThreshold desc="Item count">1000</ItemThreshold>
        <MemoryThreshold desc="KB">10000</MemoryThreshold>
      </processor>
    </httpRequestEnd>
…
    </pipelines>
…
  </sitecore>

How can I work with Sitecore Pipelines?

Existing Sitecore pipelines can be customised as outlined above and it is also possible to create a brand new pipeline from scratch

Customise existing Pipelines

First thing to do is to create a configuration patch to add the new processor class into the pipeline at the desired location.  As you can see from the code it is possible to pass variables to the processor.  Here we are adding a processor called NewsArticleLogEntryProcessor into the httpRequestBegin pipeline after the ItemResolver

<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
  <sitecore>
    <pipelines>
      <httpRequestBegin>
        <processor type="Fourbyclub.CustomCode.CustomCode.Pipelines.httpRequestBegin.NewsArticleLogEntryProcessor,Fourbyclub.CustomCode" patch:after="processor[@type='Sitecore.Pipelines.HttpRequest.ItemResolver, Sitecore.Kernel']">
          <NewsArticleTemplateID>{B871115E-609F-44BB-91A4-A37F5E881CA6}</NewsArticleTemplateID>
        </processor> 
      </httpRequestBegin>
    </pipelines>
  </sitecore>
</configuration>

Then we need to create the processor.  Inherit the HttpRequestProcessor and Implement the Process method.  All we are doing here is writing to the log if the requested item is a NewsArticle.

namespace Fourbyclub.CustomCode.CustomCode.Pipelines.httpRequestBegin
{
    using Sitecore.Pipelines.HttpRequest;
    using Sitecore.Diagnostics;

    // TODO: \App_Config\include\NewsArticleLogEntryProcessor.config created automatically when creating NewsArticleLogEntryProcessor class.

    public class NewsArticleLogEntryProcessor : HttpRequestProcessor
    {
        
        // Declare a property of type string:
        private string _newsArticleTemplateID;
        public string NewsArticleTemplateID { get { return _newsArticleTemplateID; } set { _newsArticleTemplateID = value; } }

        public override void Process(HttpRequestArgs args)
        {
            Assert.ArgumentNotNull(args, "args");
            if ((Sitecore.Context.Item != null) && (!string.IsNullOrEmpty(_newsArticleTemplateID)))
            {
                Assert.IsNotNull(Sitecore.Context.Item, "No item in parameters");
                // use util to get id from string property
                if (Sitecore.Context.Item.TemplateID == Sitecore.MainUtil.GetID(_newsArticleTemplateID))
                {
                    // view in log file later, so add FourbyclubCustomCode
                    Log.Info(string.Format("FourbyclubCustomCode: News Article requested is {0} and the item path is {1}", Sitecore.Context.Item.DisplayName, Sitecore.Context.Item.Paths.FullPath), this);
                }
            }
        }

    }
}

Create a new Pipleline

To create and new pipeline is a little more work but still very simple.  The first thing to do is to declare the pipeline with a configuration patch

<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
  <sitecore>
    <pipelines>
      <logWriter>
        <processor type="Fourbyclub.CustomCode.CustomCode.Pipelines.logWriter.logWriterProcessor,Fourbyclub.CustomCode" />
      </logWriter>
    </pipelines>
  </sitecore>
</configuration>

The XML above will create a pipeline called logWriter that has a single processor called logWriterProcessor, which will be in the Fourbyclub.CustomCode.dll.

Pipelines must pass a PipelineArgs object to each processor as it is called so that needs to be defined

using Sitecore.Pipelines;

namespace Fourbyclub.CustomCode.CustomCode.Pipelines.logWriter
{
    public class LogWriterPipelineArgs : PipelineArgs
    {
        public string LogMessage { get; set; }
    }
}

At least one processor is needed to do the work of our pipeline

using Sitecore.Diagnostics;

namespace Fourbyclub.CustomCode.CustomCode.Pipelines.logWriter
{
    public class logWriterProcessor
    {
        public void Process(LogWriterPipelineArgs args)
        {
            Log.Info(string.Format("FourbyclubCustomCode: The message was {0}", args.LogMessage), this);
        }
    }
}

Finally we need to invoke the pipeline in our code somewhere.  Instantiate the LogWriterPipelineArgs and set the LogMessage.  Then call CorePipeline.Run and pass it the name of the pipeline and the args.object

var pipelineargs = new LogWriterPipelineArgs();
pipelineargs.LogMessage = "Requested item is not a News Article";
CorePipeline.Run("logWriter", pipelineargs);

Conclusion

Thank you for reading and I hope that this short introduction to Sitecore Pipelines has shown the power of pipelines to customise Sitecore and help to build maintainable code.  However we should always check if there is a way we can implement something using existing Sitecore functionality rather than going for a pipeline as a first resort. As with any customisation does each pipeline or processor added have a potential to increase the challenge of Sitecore upgrades?

Aceik’s Jason Horne and Thomas Tyack Win Sitecore Most Valuable Professional Technology Award

Aceik is thrilled to share that our very own, CEO & Founder, Jason Horne and Solutions Architect, Thomas Tyack have again been named a Most Valuable Professional (MVP) in the Technology category by Sitecore®, the global leader in digital experience management software.

Jason and Thomas are two of only seven named Technology MVPs in Australia. This is the fifth consecutive year that Sitecore has honoured Jason with the Technology MVP award, and the second year for Thomas.

Recognising professionals within the Sitecore community who actively apply their talent and expertise to help others best utilise Sitecore products to deliver premier customer experiences, the MVP program is now in its 14th year. Of more than 13,000 certified developers and over 24,000 active community participants, the 316 MVPs around the world are truly an elite group. This year’s MVPs were selected for the quality, quantity and impact of the contributions they made in 2019, including the sharing of product expertise and mastery of the Sitecore platform to support both partners and customers.

And we are absolutely stoked to have two globally-recognised Sitecore MVPs as part of our team, a true accolade to their commitment to our customers. A huge congratulations to the other 2020 MVPs around the world!

A little about Jason Horne

Jason founded Aceik, a digital consultancy that specializes in the implementation, training and support of Sitecore solutions in 2014. Jason’s vision back then, to place customer satisfaction at the core of all Sitecore projects, still guides the team’s direction today.

Jason has delivered numerous large Sitecore projects, including RAA, Village Roadshow and UniSuper (to name just a few) whilst always holding his team to the highest levels of transparency, communication and technical standards.

Learn more about Thomas Tyack

Thomas is a Technical Lead / Architect that has built a career in content management with over 14 years’ experience across 5 different content management systems. Working for high profile agencies in Australia and the UK he has experience directing web teams across a broad cross section of clients in both the enterprise and start-up sectors.

As a Technical Lead, Thomas’ main toolset strengths are around object orientated programming, .NET, web service API’s and modern java script frameworks like React. His ability to help clients deliver a program of work by bringing teams and projects into line with best practice tools, processes and documentation should be well noted.

Sitecore MVP Program

More information can be found about the MVP Program on the Sitecore MVP site:http://mvp.sitecore.com.