My Sitecore SUGCON 2023 Takeaways – Day 2

> DAY ONE - If you haven't read about Day One you can read it here.

SUGCON DAY 2

IMG_0478

The 2nd Day of SUGCON started bright an early so after a quick breakfast and cup of tea at the hotel I headed down to the first session I’d planned to see.

Rob’s session is one of the key sessions I really didn’t want to miss this year. A few clients I’ve spoken to recently (and other Sitecore Dev’s I’ve chatted to at SUGCON so far) are facing this challenge:

‘How do we move to XM Cloud from XP and what do we need to consider?’

– so I was keen to learn from Rob’s experiences.

Migrating advanced Sitecore implementations to XM Cloud – Rob Habraken

rob-xm-cloud-banner

Rob started with telling us the differences with XM Cloud and explaining how publishing works differently (given you publish to the Edge):

IMG_0638
IMG_0640

Rob then shared a typical XP implementation diagram and showed how XP Differs as integrations and functionality is moved into the head application:

IMG_0642

He then discussed what is included and not included in XM Cloud in detail. Martin shared some similar slides the day before, but I think these were a little clearer so I didn’t include them in the previous post:

IMG_0644
IMG_0645

This was also a pretty cool comparison of XP vs XM Cloud equivalent features:

IMG_0646

Rob then discussed the Migration approach to XM Cloud. There was a lot of really useful info here about things to consider and how to get your project prepared for the migration and how to tackle it:

IMG_0648
IMG_0649
IMG_0650
IMG_0652

IMG_0653

Next up was the the different development approaches and workflow. I’ve talked about these before but I didn’t know much about option 3 at all. I guess most Sitecore developers (especially in a small team) will use option 1, but option 3 is a really good approach for being able to use local content for your development without having to push it to XM Cloud:
IMG_0654
IMG_0655
IMG_0656
IMG_0657

Rob then went on to explain in detail about how Content Resolvers don’t work if they are dynamic and only static ones do. It’s possible to use some out of the box ones or implement your own GraphQL Content Resolver:

IMG_0659
IMG_0662
IMG_0663
IMG_0664

This is an example of Bread crumbs in XM Cloud and a GraphQL search query:

IMG_0666

IMG_0667

Rob finished his talk with a summary of the benefits of XM Cloud. The shift in Development domain and thinking is the tricky part for a lot of Sitecore Developers I feel:
IMG_0668

 

Rendering your data in headless – 101 different ways
– Mike Edwards

mike-headless-banner

I’ve known Mike for a number of years now and he’s always an good speaker so I was looking forward to Mike sharing his learnings from his headless journey.

IMG_0673
IMG_0674

Mike started by lamenting how things used to be easy in the World of MVC and server-side development and then with all the JQuery and JS frameworks things became pretty bloated.

Things have moved on a lot now in FE development though and there are now many different options for building Headless websites in Sitecore, some of these I’m aware of or have experimented with – Others I’ve not heard of, such as ‘Island Architecture’.

IMG_0674
IMG_0676
IMG_0677
IMG_0678

SPAs bring their own set of problems in terms of page load times and indexability so Mike went into Hydration and Partial Hydration techniques and approaches that try to solve these issues:

IMG_0679
IMG_0680

Then Mike explained more about Partial Hydration examples and Island Architecture. Island Architecture lets you create your web app with pure HTML and CSS for all the static content but then add in regions/placeholders of dynamic content to support interactive ‘islands’ of content. Given the rest of the page is static it downloads really quickly and is available to use faster.

IMG_0681
IMG_0683

Mike then covered Resumability, Edge/Serverless and tools such as Storybook and Hydration Payload.

IMG_0684
IMG_0685
IMG_0686
IMG_0687

There are some Challenges and limitations which need to be re-address:

IMG_0689
IMG_0690
IMG_0692
IMG_0693

Finally Mike ended with saying that this is the future and we need to embrace the new world.
IMG_0694

It was a really interesting talk and gave me a lot to think about and research further. The following talks were 15 minute lightning talks until lunch.

Leverage Sitecore Connect for Sitecore CDP – Sarah O’Reilly

IMG_0695

I’d heard a fair bit about Connect but I’ve not really seen much about how it actually works. So I was looking forward to this session

Sarah took us through an example of using Connect to import user segment data from CDP into Google Ads.

IMG_0696 IMG_0703

Once the export was setup to build from CDP the steps were then configured in Connect to sync to Google Ads:
IMG_0712
IMG_0714

There are tons of Apps supported and different recipes defined and it was impressive to see the options for building logic such as if statements / for loops data mapping and manipulation all within Connect.

IMG_0709

This was an insightful session and really interesting to see how it works. I can see how it could be used to help with migrating to XM Cloud from XP or another CMS platform.

Sitecore components explained for your marketers – Ugo Quaisse

The next session was about the Sitecore Components builder in Pages in XM Cloud. I’ve heard a bit about this but not seen much of it in detail. I was hoping to see a full demo of it. I guess at the session was only 15 minutes there wasn’t time, but I still learned quite a bit about how it works.

IMG_0715
IMG_0716
IMG_0717
IMG_0719

The Component Builder can be used without any development or code required at all. First Themes are setup with colours, fonts and breakpoints configured.

Then datasources are setup and mapped from either a url or json or GraphQL.

IMG_0720

Then the components ‘look and feel’ – layout, dimensions and sizing can be configured in the Builder. This looks pretty neat. Then versioning and publishing is setup for the Component.

IMG_0721

IMG_0722

Lastly some details were shared around the benefits for digital creatives, it’s possible to get Sites built very quickly and easily using Components Builder.

IMG_0723
IMG_0724
IMG_0726
IMG_0727

 

Leveraging XM Cloud APIs and Webhooks to powerup integrations – Ramkumar Dhinakaran & Elakkuvan Rajamani

IMG_0740

After lunch it was time for another session, this time on Webhooks. The use-case here was the XM Cloud Lighthouse Integration which would do an automated quality check of pages using Webhooks and report on it.

IMG_0731

IMG_0742
IMG_0745

Depending on the integration required it might not be best to use a Webhook:
IMG_0756
IMG_0758

Quite a lot of detail was shared with how this all works and integrates.

IMG_0735
IMG_0736
IMG_0737
IMG_0747

There were some links and takeaways shared at the end.

IMG_0763

 

Sitecore Search: Real case PoC – Sebastian Winslow & Jesper Balle

IMG_0766

The 2nd to last session for the day was on the Sitecore search (based on Discover) which I was keen to learn about more as I didn’t know much about how it worked.

IMG_0770
IMG_0772
IMG_0773

CEC looks pretty powerful and can be used to manage search, performance is key and widgets can be configured for search and catalog:

IMG_0774
IMG_0776
IMG_0778
IMG_0779

Some dev resources and admin info were shared:

IMG_0780
IMG_0782

The use case for search was a property Site. There is still some features that need to be built.

IMG_0783
IMG_0785
IMG_0789
IMG_0790

Some info was then provided on Triggers to get the content, Request and document extractors to process and manipulate the content.

IMG_0791
IMG_0792
IMG_0793
IMG_0794

Search API endpoints, results response, API Explorer and ability to refine the widgets.

IMG_0796
IMG_0798
IMG_0799
IMG_0801

It’s early days and the search SDK is still not there yet but it’s coming. Be careful with how much content you try and index when testing but there are some significant benefits to using it.

IMG_0803
IMG_0805

This was a really informative session and gave me all the info I was looking for about how to go about implementing search.

Experiences with Content Hub One – Journey of relaunching our Usergroup website – Katharina Luger & Christian Hahn

IMG_0807

Then it was time for my last session of the day on how the Sitecore User Group Germany rebuilt their site as an SPA using Content Hub One.

The slide below was probably the simplest comparison I saw all SUCON of the differences between XM Cloud and Content Hub One.

IMG_0808
IMG_0811
IMG_0816
IMG_0818

There are 7 Steps to component creation:

IMG_0821
IMG_0822
IMG_0823
IMG_0824
IMG_0825
IMG_0826
IMG_0828

Lastly there were some challenges faced.

IMG_0831

This was a really great session and I’m looking forward to working with Content Hub One in the future.

Virtual Closing Keynote by Scott Hanselman

IMG_0833

There was then an really entertaining and insightful talk from Scott Hanselman. He had some great advice, wisdom and stories to tell to us and I think everyone in the room was pretty captivated by his talk.

IMG_0848

With that it was the end of SUCON 2023, there was a big round of applause for all the organisers. These events take a hell of a lot of organising and a real commitment from everyone involved.

 

IMG_0855

It was time to go and have a few beers and reflect on what was a another brilliant SUGCON.

IMG_0862
Hopefully this is useful info for anyone that couldn’t attend this year or had too many beers and forgot what they learned :-).

Adding Items to a Custom Sitecore Seach Index using SiteCron

old-books

Over the years working with Sitecore I’ve had to create custom indexes and add items to them for most clients I’ve worked for. I’ve generally written a Search Crawler and Search Indexer to handle this but it’s always seemed like a lot of code to manage just to add a few items to an index and temperamental to control the indexing frequency accurately. I’ve also had many issues with Indexes being out of Sync in the past due to Sitecore Events not firing on CD instances etc.

I’ve tried various approaches to simplifying this in the past but unfortunately never got this working. However this came up again on a recent project and I was successful this time – so decided I’d share my approach and code.
Note in this example I’m using Solr but in Theory this same code should work with Azure Search also.

In simple terms the approach is to:

1) Create a Custom Index – to store my content (in this case Blogs)
2) Create a Search Indexing Service – which will retrieve the Items and add them to the Custom index
3) Create an SiteCron Indexing Job – which will call my Indexing Service to Index the Items on a regular basis
4) Create a Search Results Page – which will display the search results from the Index

Benefits of this approach

  • Less Code to write and manage
  • Can control how often the indexing runs very accurately (using SiteCron) and this persists across App Service / IIS Restarts.
  • Easy to test and maintain

1) Creating a Custom Solr Index

I’m not going to go into this process too much as it’s documented well elsewhere but essentially you need to copy on of the out of the box solr folders, rename it and also update the core.properties file. For this example I’ve created and index called sc93_blogs_index:

custom-index-folder

Configuration

You will also need to add 2 configuration files for the custom Index like so to define the index name, strategy (of manual) and configure the fields to include. Amend these as required for your use-case:

Index Config:
Index Fields Config:

 

2) Search Indexing Service

The next step is to create our Search Indexing Service. This will get the blog items and add them to the index. This could easily be pulling Info from an datatabase, API or File instead if needed.  I’ve called mine BlogPostSearchService:

 public class BlogPostSearchService : ISearchService
 {
  ...
 }

I also added an interface with  two methods:

public interface ISearchService
{
   int IndexContent();

   BlogPostSearchResultsModel GetResults(BlogPostSearchResultsModel blogPostSearchResultsModel, string searchTerm, int resultsPerPage, int currentPage);

}

Index Content Method

The IndexContent() Method is like so. Note this code is not optimal if you have more than a few hundred items within a folder, you may wish to re-structure your items differently:
 

Get Content Method

The GetContent() Method is as follows:

Supporting Models / Classes

There are various supporting models and classes used in the above code. Below are the key ones.

BlogPostSearchResult

My Blog Posts just have two additional properties so this is pretty simple:
public class BlogPostSearchResult: SearchResultItem
{
    [DataMember]
    [IndexField("Title")]
    public string Title { get; internal set; }

    [DataMember]
    [IndexField("Description")]
    public string Description { get; internal set; }
}

BlogPostSearchResultsModel

This Model is used to hold my search results and some other properties about the search results for use in the View:

public class BlogPostSearchResultsModel
{
    public string SearchTerm { get; set; }
    public IPagedList<BlogPostSearchResult> SearchResults { get; set; }
    public int TotalNumberOfResults { get; set; }
    public int NoOfResults { get; set; }
    public int Page { get; set; }
}

Settings

You will notice there are some settings used in the code such as for the Blog Post Items Path. Add a Sitecore patch file for these and configure them as needed.

Paged List

I’m using an Nuget Package for PagedList, this is a good one if you want to use one too: https://github.com/dncuug/X.PagedList

3) SiteCron Indexing  Job

The next step is to create our SiteCron Job which will be responsible for indexing the content. This calls the IndexContent() method on the service. Obviously this needs to match your SiteCron Job name above.
See my post here about logging to the last run log etc if you’d like to do that too.

  This is then setup in SiteCron to run like so, schedule it to run as needed: sitecron-job 

4) Search Results Page

The last step is to display the Search Results. Create a page in Sitecore using whatever template you use. Then Create an Controller Rendering and View in Sitecore, reference the Controller below and add the rendering to the page.

Controller

The Controller looks like so:

View

The View, this is a simplified version:

The Result

So once you’ve done all the above you should end up with something like the following:

search-results-page-blogs

 

Hopefully this helps someone else who need to implement a custom search and illustrates an alternative approach that could work for them.

Creating Multiple Uniquely Named Solr Instances For Sitecore Development

solr-red Since the release of Sitecore 9.x and above Solr has been the default Search service and there is an requirement to install Solr with an SSL Certificate in order to use SIF to install Sitecore.
To simplify this I’ve been using this Powershell Script that Jeremy Davis kindly created for a while now.

In general it works brilliantly but if you want to keep all your Solr instances in C:\Solr as soon as I try to install a 2nd or 3rd instance of the same version of Solr (e.g a 2nd solr-6.6.2 instance for 9.02) I run into issues.
The script assumes that you don’t already have a folder called “\solr-6.6.2” in C:\Solr and fails. It will also fail on a number of other steps such as the cert name, service name and zip download/extraction.

Therefore I’ve modified the Script to support passing in a suffix which creates a unique instance of Solr using a $solrSuffix variable for various steps in the script.

Just set this variable to something that makes sense for that instance of Solr and run it e.g:

$solrSuffix = 902dev;

You should then have an unique instance of Solr and you can keep running the script again and again as long as the $solrSuffix is unique and you update the values of  $solrPort and $solrHost each time also.

unique-solr solr-installed

 

 

 

The script below is setup for Sitecore 9.1 installs (using Solr 7.2.1), but if you change the $solrVersion to 6.6.2 and set the other 3 variables mentioned above you can use it for Sitecore 9.0.x installs too.

This updated script has saved me quite a bit of time over the past few months, hopefully others will find this useful too.
Thanks again to Jeremy for writing the original script.