<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Jay Bonning</title>
    <description>The latest articles on Forem by Jay Bonning (@mrpipedream).</description>
    <link>https://forem.com/mrpipedream</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1346766%2F0255f4eb-107b-4890-842b-8c81d5b08e3a.png</url>
      <title>Forem: Jay Bonning</title>
      <link>https://forem.com/mrpipedream</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/mrpipedream"/>
    <language>en</language>
    <item>
      <title>Sitecore Symposium Day 1</title>
      <dc:creator>Jay Bonning</dc:creator>
      <pubDate>Thu, 17 Oct 2024 15:03:40 +0000</pubDate>
      <link>https://forem.com/mrpipedream/sitecore-symposium-day-1-1bp6</link>
      <guid>https://forem.com/mrpipedream/sitecore-symposium-day-1-1bp6</guid>
      <description>&lt;p&gt;Well, it was my day 1 and think the key take away is &lt;strong&gt;AI everywhere&lt;/strong&gt;. It will be key to delivering your organization's vision out to the world.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sitecore Stream
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.sitecore.com/products/sitecore-stream" rel="noopener noreferrer"&gt;Sitecore Stream&lt;/a&gt; looks to do amazing work for anyone doing digital marketing. Being able to coordinate your brand with Gen AI on the back end looks to button up how your organization presents sounds like a dream come true. This will even be coming to XP!&lt;/p&gt;

&lt;h2&gt;
  
  
  Content Hub
&lt;/h2&gt;

&lt;p&gt;AI is going to be helping you with your content as well. Sitecore Steam will be able to be integrated directly into content hub, or if you already have a brand aware AI tool you will be able to integrate that. Providing a lot of help to content authors who have to do the crucial work of augmenting the metadata on content to make it easier to use/reuse. Many thanks to Jennifer Johnson and Heather Nicholis who shared their journey through around this.&lt;/p&gt;

&lt;h2&gt;
  
  
  Changes to SEO
&lt;/h2&gt;

&lt;p&gt;Tiffany Laster and Megan Mueller Jensen brought an important lesson about the changes in SEO. Don't forget to be human. We have a ton of tooling, AI or not, to help generate content. This can lead to some bland/boring content that people don't engage with. Your voice needs to come through to maintain high rankings when it comes to people finding and interacting with your brand.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Setup and Use Sitecore CMP Connector. Part 1</title>
      <dc:creator>Jay Bonning</dc:creator>
      <pubDate>Thu, 06 Jun 2024 19:16:22 +0000</pubDate>
      <link>https://forem.com/mrpipedream/setup-and-use-sitecore-cmp-connector-1f7f</link>
      <guid>https://forem.com/mrpipedream/setup-and-use-sitecore-cmp-connector-1f7f</guid>
      <description>&lt;p&gt;That sure is a nice Sitecore Content Hub you've got there. It is a good bet that you would like to use some of that content on XM Cloud. So lets do that.&lt;/p&gt;

&lt;p&gt;This might get a bit long. So, briefly, here is what I am going to be describing how to do:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Setup an Action and Trigger inside of Content Hub&lt;/li&gt;
&lt;li&gt;Setup the CMP connector inside of your XM Cloud application&lt;/li&gt;
&lt;li&gt;Setup data mappings for the content hub items.&lt;/li&gt;
&lt;li&gt;List some issues I had along the way and how they were overcome.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;   &lt;br&gt;
Assumptions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You have access to create Triggers and Actions in Content Hub.&lt;/li&gt;
&lt;li&gt;The content item you need to sync has already been created. I will show off what the sample one looks like, but I will not go into its creation.&lt;/li&gt;
&lt;li&gt;You have access to add variables to your Sitecore XM Cloud project.&lt;/li&gt;
&lt;li&gt;You already setup an Oauth connection string setup in Content Hub that is being used to connect to the DAM. We will reuse this for the cmp connection, but these can be different if you have difference security requirements.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;   &lt;/p&gt;

&lt;h2&gt;
  
  
  Content Hub Actions and Triggers
&lt;/h2&gt;

&lt;h2&gt;
  
  
       
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Create an action
&lt;/h3&gt;

&lt;p&gt;Actions are the way we communicate between the two systems and triggers are ways to cause the action to fire.&lt;/p&gt;

&lt;p&gt;The action we are going to want to setup is a &lt;a href="https://doc.sitecore.com/xp/en/developers/connect-for-ch/50/connect-for-content-hub/create-a-sitecore-content-hub-action.html"&gt;service bus action&lt;/a&gt;. There are two types supported.  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;u&gt;Azure Service Bus&lt;/u&gt; - An azure service bus setup and maintained by you. So some of this setup can be useful for any other downstream application that might want to use the date being emitted by Content Hub.&lt;/li&gt;
&lt;li&gt;
&lt;u&gt;M Azure Service Bus&lt;/u&gt; - A service bus topic setup and maintained by Sitecore.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For this we are going to be using the 'M Azure Service Bus' because I don't want to have to setup and maintain anything myself. When you add a new action select the Type "M Azure Service Bus" and choose "Topic" as the Destination Type.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh50vx85bw36kiewsvqbh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh50vx85bw36kiewsvqbh.png" alt="Image description" width="800" height="636"&gt;&lt;/a&gt;  &lt;/p&gt;

&lt;p&gt;Make sure to copy the values that are generated in "Hub In" and "Hub Out". you will be using these later to setup the connection in XM Cloud.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3tgxiy3f8ft9honux8pa.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3tgxiy3f8ft9honux8pa.png" alt="Image description" width="800" height="491"&gt;&lt;/a&gt;  &lt;/p&gt;

&lt;p&gt;Now we have a way to send the data, we need a way to trigger the information exchange to happen.&lt;/p&gt;

&lt;h2&gt;
  
  
       
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Create a trigger
&lt;/h3&gt;

&lt;p&gt;We now need to tell Content Hub to actually send the message. For this instance we are publishing out a simple new article which has already been defined as a content item. The news article we are syncing between systems  has a title and a rich text body. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff4ghppy6neju4zwmcmit.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff4ghppy6neju4zwmcmit.png" alt="Image description" width="800" height="456"&gt;&lt;/a&gt;  &lt;/p&gt;

&lt;p&gt;It is also worth noting right now that this is also where we can see all the related taxonomy for content items in the system. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft042mzs3mocfaj3v7wyp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft042mzs3mocfaj3v7wyp.png" alt="Image description" width="800" height="229"&gt;&lt;/a&gt;  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://doc.sitecore.com/xp/en/developers/connect-for-ch/50/connect-for-content-hub/create-a-trigger.html"&gt;Setting up the trigger&lt;/a&gt; is fairly simple. We define basic information about the trigger. Here I want to make sure I check all the objectives, since I might be mutating the object later, and the execution type as "in background" so it does not stall out any of the processing. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdewkss1mr1xl7lb6ws9z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdewkss1mr1xl7lb6ws9z.png" alt="Image description" width="800" height="467"&gt;&lt;/a&gt;  &lt;/p&gt;

&lt;p&gt;The conditions can become quote specific. In this example I want to sync the object when a user has fully published the news item. The content item of "M.Content" has the information about the publish state and there is a separate publish flag that was added on the news item itself.  I need to make sure both of these conditions are matched before I perform my action. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fufwocoipa1te9rb4g4ak.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fufwocoipa1te9rb4g4ak.png" alt="Image description" width="800" height="385"&gt;&lt;/a&gt;  &lt;/p&gt;

&lt;p&gt;Now all we have to do is tie in the action we created earlier and we are all set to start sending out information.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9qz49athv0l4lwyxswg1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9qz49athv0l4lwyxswg1.png" alt="Image description" width="800" height="317"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;     &lt;/p&gt;

&lt;h2&gt;
  
  
  Setup the CMP connection on XM Cloud
&lt;/h2&gt;

&lt;p&gt;In your Sitecore XM Cloud deploy portal you will need to setup a few values to get your CMP functionality working.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;SITECORE_AppSettings_cmpEnabled_define&lt;/strong&gt; - Enables the CMP connector in the system. (yes or no)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sitecore_ConnectionStrings_CMP_dot_ContentHub&lt;/strong&gt; - Connection string to content hub. You can reuse your DAM OAuth connection string here.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sitecore_ConnectionStrings_CMP_dot_ServiceBusSubscription&lt;/strong&gt; - Name of the azure service bus subscription. &lt;u&gt;More on this later&lt;/u&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sitecore_ConnectionStrings_CMP_dot_ServiceBusEntityPathOut&lt;/strong&gt; - HUB IN connection string from the service bus action that was setup.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sitecore_ConnectionStrings_CMP_dot_ServiceBusEntityPathIn&lt;/strong&gt; - HUB OUT connection string from the service bus action that was setup&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;   &lt;br&gt;
&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzu9qoakfapxzm5obszm5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzu9qoakfapxzm5obszm5.png" alt="Image description" width="800" height="405"&gt;&lt;/a&gt;  &lt;/p&gt;

&lt;p&gt;This will cause the CMP items to start showing up inside of Sitecore.&lt;/p&gt;

&lt;p&gt;   &lt;br&gt;
Before:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkiesabiis7nc3t62rcfl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkiesabiis7nc3t62rcfl.png" alt="Image description" width="800" height="238"&gt;&lt;/a&gt;  &lt;/p&gt;

&lt;p&gt;   &lt;br&gt;
After:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9p0n983bsw68w207n25r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9p0n983bsw68w207n25r.png" alt="Image description" width="800" height="403"&gt;&lt;/a&gt;  &lt;/p&gt;

&lt;p&gt;   &lt;br&gt;
Now your application should be setup to receive information from Content Hub.&lt;/p&gt;

&lt;h2&gt;
  
  
       
&lt;/h2&gt;

&lt;h2&gt;
  
  
  Some problems we ran into
&lt;/h2&gt;

&lt;p&gt;   &lt;/p&gt;

&lt;h3&gt;
  
  
  The value for Sitecore_ConnectionStrings_CMP_dot_ServiceBusSubscription
&lt;/h3&gt;

&lt;p&gt;It was not immediately apparent what the value of this was meant to be. If you are not familiar with &lt;a href="https://learn.microsoft.com/en-us/azure/service-bus-messaging/service-bus-queues-topics-subscriptions#topics-and-subscriptions"&gt;how a topic works on Azure service bus&lt;/a&gt; it is basically a way to allow multiple "receivers" to handle the messages posted to a topic. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It was not the name of the action in Content Hub.&lt;/li&gt;
&lt;li&gt;It was not derived from the action name.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;after opening a ticket with Sitecore we did find out ours was named '&lt;strong&gt;&lt;u&gt;hub_out_subscription&lt;/u&gt;&lt;/strong&gt;'. You can try this if you are having issue with your application receiving information. you might have to open a support request to get the name of yours though.&lt;/p&gt;

&lt;p&gt;If you are setting up your own service bus, this will not be a problem. &lt;/p&gt;

&lt;p&gt;   &lt;/p&gt;

&lt;h3&gt;
  
  
  Authentication / SSO
&lt;/h3&gt;

&lt;p&gt;Working to get this up and going we also ran into an issue with authentication. Our content hub was originally setup to &lt;strong&gt;ONLY&lt;/strong&gt; accept connections over SSO. This was causing the OAuth connection between Content Hub and XM Cloud to fail. We needed to go into Content Hub settings and set 'EnableBasicAuthentication' to true.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbfq7wbm21q3bnfqedr6e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbfq7wbm21q3bnfqedr6e.png" alt="Image description" width="800" height="512"&gt;&lt;/a&gt;  &lt;/p&gt;

&lt;p&gt;Setting up data mappings coming in part 2&lt;/p&gt;

</description>
      <category>sitecore</category>
      <category>cmp</category>
      <category>xmcloud</category>
    </item>
    <item>
      <title>Setup XM Cloud Multi-site on Netlify</title>
      <dc:creator>Jay Bonning</dc:creator>
      <pubDate>Wed, 17 Apr 2024 17:06:59 +0000</pubDate>
      <link>https://forem.com/mrpipedream/setup-xm-cloud-multi-site-on-netlify-531e</link>
      <guid>https://forem.com/mrpipedream/setup-xm-cloud-multi-site-on-netlify-531e</guid>
      <description>&lt;p&gt;We had some interesting struggles getting XM Cloud multi-site to work on Netlify. We would like to make it easier for other people to get this setup and running. Many thanks to &lt;a href="https://www.linkedin.com/in/richardseal/" rel="noopener noreferrer"&gt;Richard Seal&lt;/a&gt; for his help  getting this all setup correctly. &lt;/p&gt;

&lt;h3&gt;
  
  
  A couple of notes before we start
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;This solution will pertain to a single Netlify environment that will be hosting several different websites at once.&lt;/li&gt;
&lt;li&gt;Some of the solutions recommended below are known issues with Sitecore, and may not be steps you need to take in the future. At the time of writing this the application was on version 21.6.4 of &lt;a href="https://github.com/Sitecore/jss" rel="noopener noreferrer"&gt;Sitecore JSS&lt;/a&gt;. I will try to remember to indicate this, but I make no promises ahead of time.&lt;/li&gt;
&lt;li&gt;Several images will contain information that is blurred out to maintain the confidentiality of the environment. Many pixels were harmed in the creation of this post.&lt;/li&gt;
&lt;li&gt;There might be some sarcasm along the way. &lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Setup and The Problem
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdqcytiyfk8e60xv8vr11.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdqcytiyfk8e60xv8vr11.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For this implementation the customer was looking to simplify the deployment of their smaller sites. So we setup several sites within one XM Cloud tenant.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9ppmb6wr5l0liojt6skz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9ppmb6wr5l0liojt6skz.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Each of those had the site grouping setup with the appropriate Hostname, sitename, Predefined application rendering host, etc.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fposdvs8ovufnmcmfm6am.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fposdvs8ovufnmcmfm6am.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;SXA Site Manager was even showing green lights across the board. &lt;/p&gt;

&lt;p&gt;The problem that manifested is that when we would attempt to load any of the sites, we would get a continual reload of the page. Several times a second it would send a new request to the server. This didn't seem like an ideal solution.&lt;/p&gt;

&lt;p&gt;If you page is doing this, open the developer tools in the browser. You will likely see it is attempting to get resources from the wrong website.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Solution
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Netlify Setup
&lt;/h3&gt;

&lt;p&gt;So everything above is setup how it is supposed to be setup. Let's go to Netlify setup and pull out some juicy details.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx6fqg27qg8znlplwiqoa.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx6fqg27qg8znlplwiqoa.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;FETCH_WITH&lt;/strong&gt; : Usually going to be "GraphQL". We are not sure if this is really needed, but it does not hurt&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;PUBLIC_URL&lt;/strong&gt; : This should be set to nothing. The field should be empty. See I am not lying 
&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fylf3ttz9terd5t8z31eu.png" alt="Image description"&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SITECORE_EDGE_CONTEXT_ID&lt;/strong&gt; : This is the context id you get from the &lt;a href="https://deploy.sitecorecloud.io/" rel="noopener noreferrer"&gt;Sitecore deploy site&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SITECORE_SITE_NAME&lt;/strong&gt; : This should correspond to the name of one of the sites above. Just one, no more. The rest is taken care of by the Nextjs multi-site plugin.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Code Changes
&lt;/h3&gt;

&lt;p&gt;With that, Netlify should be setup. But wait, there's more, this is also what might be fixed in the version of the code you are using. So this may not be applicable.&lt;/p&gt;

&lt;p&gt;We need to create an &lt;em&gt;.env&lt;/em&gt; file with no values set. So open up the directory with your Nextjs application. (e.g. &lt;em&gt;/src/'project name'/.env&lt;/em&gt;). I chose to copy the &lt;em&gt;starter.env&lt;/em&gt; file because it had all the fields we needed to set. All the fields should be cleared though. In essence what happening is we are creating some default values for the websites in Netlify, and then using the Netlify environment variables to overwrite these defaults.  &lt;/p&gt;

&lt;p&gt;Here is a sample of that &lt;em&gt;.env&lt;/em&gt; file in case you had deleted it:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# For development purposes, note Next.js supports a .env.local
# file, which is already configured to be git ignored.
# Read more about Next.js support of environment variables here:
# https://nextjs.org/docs/basic-features/environment-variables

# The public URL to use for absolute URLs, which are required when
# the Next.js app is run within Sitecore editors.
# This should match the `serverSideRenderingEngineApplicationUrl`
# in your Sitecore configuration (see \sitecore\config\sxastarter.config).
# Be sure to update these values accordingly as your public endpoint changes.
# See https://jss.sitecore.com/docs/fundamentals/services/view-engine
PUBLIC_URL=

# To secure the Sitecore editor endpoint exposed by your Next.js app
# (`/api/editing/render` by default), a secret token is used. This (client-side)
# value must match your server-side value (see \sitecore\config\sxastarter.config).
# We recommend an alphanumeric value of at least 16 characters.
JSS_EDITING_SECRET=

# Your Sitecore API key is needed to build the app. Typically, the API key is
# defined in `scjssconfig.json` (as `sitecore.apiKey`). This file may not exist
# when building locally (if you've never run `jss setup`), or when building in a
# higher environment (since `scjssconfig.json` is ignored from source control).
# In this case, use this environment variable to provide the value at build time.
SITECORE_API_KEY=

# Your Sitecore API hostname is needed to build the app. Typically, the API host is
# defined in `scjssconfig.json` (as `sitecore.layoutServiceHost`). This file may
# not exist when building locally (if you've never run `jss setup`), or when building
# in a higher environment (since `scjssconfig.json` is ignored from source control).
# In this case, use this environment variable to provide the value at build time.
SITECORE_API_HOST=

# Your GraphQL Edge endpoint. This is required for Sitecore Experience Edge.
# For Sitecore XM, this is typically optional. By default, the endpoint is calculated using
# the resolved Sitecore API hostname + the `graphQLEndpointPath` defined in your `package.json`.
GRAPH_QL_ENDPOINT=

# Your Sitecore app name (also used as the default site name). Overrides 'config.appName' defined in a package.json
# Get this from the site &amp;gt; Settings &amp;gt; Developer settings , eg: 'brandstudio'
SITECORE_SITE_NAME=

# Your default app language.
DEFAULT_LANGUAGE=

# How many times should GraphQL Layout, Dictionary and ErrorPages services retry a fetch when endpoint rate limit is reached
GRAPH_QL_SERVICE_RETRIES=

# The way in which layout and dictionary data is fetched from Sitecore
FETCH_WITH=

# Indicates whether SSG `getStaticPaths` pre-render any pages
# Set the environment variable DISABLE_SSG_FETCH=true
# to enable full ISR (Incremental Static Regeneration) flow
DISABLE_SSG_FETCH=

# Sitecore JSS npm packages utilize the debug module for debug logging.
# https://www.npmjs.com/package/debug
# Set the DEBUG environment variable to 'sitecore-jss:*' to see all logs:
#DEBUG=sitecore-jss:*
# Or be selective and show for example only layout service logs:
#DEBUG=sitecore-jss:layout
# Or everything BUT layout service logs:
DEBUG=

# An optional Sitecore Personalize scope identifier.
# This can be used to isolate personalization data when multiple XM Cloud Environments share a Personalize tenant.
# This should match the PAGES_PERSONALIZE_SCOPE environment variable for your connected XM Cloud Environment.
NEXT_PUBLIC_PERSONALIZE_SCOPE=

# Timeout (ms) for Sitecore CDP requests to respond within. Default is 400.
PERSONALIZE_MIDDLEWARE_CDP_TIMEOUT=

# Timeout (ms) for Sitecore Experience Edge requests to respond within. Default is 400.
PERSONALIZE_MIDDLEWARE_EDGE_TIMEOUT=

#Get this context from the 
SITECORE_EDGE_CONTEXT_ID=
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;That is just about it. You will likely need to do a build and deploy on Netlify to pick everything up. Publishing might not be a bad idea either.&lt;/p&gt;

&lt;p&gt;I welcome your comments or questions. Together we make more time to do the fun things around implementations.&lt;/p&gt;

</description>
      <category>sitecore</category>
      <category>xmcloud</category>
      <category>netlify</category>
    </item>
    <item>
      <title>Add CSP to XMCloud</title>
      <dc:creator>Jay Bonning</dc:creator>
      <pubDate>Mon, 11 Mar 2024 21:14:37 +0000</pubDate>
      <link>https://forem.com/mrpipedream/add-csp-to-xmcloud-5cc3</link>
      <guid>https://forem.com/mrpipedream/add-csp-to-xmcloud-5cc3</guid>
      <description>&lt;p&gt;It is common that you are going to need to pull in external content and use or display it with your website. So, we need to tell the browser where those assets can come from by setting a few values in the header.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Plugin
&lt;/h2&gt;

&lt;p&gt;This new file will be based on the &lt;a href="https://github.com/sitecorelabs/xmcloud-foundation-head/blob/main/src/sxastarter/src/lib/next-config/plugins/cors-header.js"&gt;cors-header.js&lt;/a&gt; that is part of the base packages for XMCloud. So we need to create a new plug-in file. I named mine 'csp-header.js'.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;src\&amp;lt;project name&amp;gt;\src\lib\next-config\plugins\csp-header.js&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const config = require('../../../temp/config');

/**
 * @param {import('next').NextConfig} nextConfig
 */
const cspHeader = (nextConfig = {}) =&amp;gt; {
  if (!config.sitecoreApiHost) {
    return nextConfig;
  }
  return Object.assign({}, nextConfig, {
    async headers() {
      const extendHeaders = typeof nextConfig.headers === 'function' ? await nextConfig.headers() : [];

      var fullCSP = '';

      fullCSP = fullCSP.concat(concatAttributes('default-src', config.customCSPDefault));
      fullCSP = fullCSP.concat(concatAttributes('img-src', config.customCSPImg));


      if(fullCSP.length &amp;gt; 0) {
        return [
          ...(await extendHeaders),
          {
            source: '/:path*',
            headers: [
              {
                key: 'Content-Security-Policy',
                value: fullCSP,
              },
            ],
          }
        ];
      }
      else { return [ ...(await extendHeaders) ];}
    },
  });
};

function concatAttributes(cspType, cspValue) {
  var returnAttribute = '';
  if(cspValue !== 'undefined' &amp;amp;&amp;amp; cspValue.length &amp;gt; 0) {
    returnAttribute = cspType.concat(' ', cspValue.replace(/\\/g, ''), ';');
  }
  return returnAttribute;
}

module.exports = cspHeader;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There are a couple of things to point out here. I chose to pull this information in from a config so it could be changed. You could easily just put your CSP values in place of these lines&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;fullCSP = fullCSP.concat(concatAttributes('default-src', config.customCSPDefault));
fullCSP = fullCSP.concat(concatAttributes('img-src', config.customCSPImg));
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It is also worth noting that you can also customize which pages this applies by adjusting the source.  &lt;/p&gt;

&lt;p&gt;&lt;code&gt;source: '/:path*',&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The last thing that you will need to know is you will &lt;u&gt;need top stop and start your instance&lt;/u&gt; before this plugin is picked up by the application. Expect a decent amount of &lt;code&gt;up.ps1&lt;/code&gt; and &lt;code&gt;down.ps1&lt;/code&gt; while you are doing your testing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Adding Config Entries
&lt;/h2&gt;

&lt;p&gt;Working through this on a docker instance. I wanted to be able to place a value directly in the &lt;code&gt;.env&lt;/code&gt; similar to how it would get set when you are setting up a hosting environment.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CUSTOM_CSP_DEFAULT="\'self\' \'unsafe-inline\' \'unsafe-eval\' data:"
CUSTOM_CSP_IMG="\'self\' data:"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I added these to my &lt;code&gt;.env&lt;/code&gt;, but they need to wired into the config to be used by the plugin. To do this you will need to edit the file:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;src\&amp;lt;project name&amp;gt;\scripts\generate-config.ts&lt;/code&gt; &lt;/p&gt;

&lt;p&gt;I removed some lines and replaced them with &lt;code&gt;...&lt;/code&gt; below, but you will want to add an entry for each config line you want incorporated. Note that you can use the parameter directly, or use the &lt;code&gt;constantCase&lt;/code&gt; function to pull it in. It will make the  translation between the value &lt;code&gt;CUSTOM_CSP_DEFAULT&lt;/code&gt; to  &lt;code&gt;customCspDefault&lt;/code&gt; when it is called.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const defaultConfig: JssConfig = {
...
  customCSPDefault: process.env[`${constantCase(`customCspDefault`)}`],
  customCSPImg: process.env[`${constantCase(`customCspImg`)}`],
...
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Thanks
&lt;/h2&gt;

&lt;p&gt;A lot of this came from help I received in the Sitecore Slack community. If you are not already there, I suggest you sign up.&lt;/p&gt;

&lt;p&gt;Also the people on my team who put up with me on a daily basis.&lt;/p&gt;

</description>
      <category>sitecore</category>
      <category>xmcloud</category>
    </item>
  </channel>
</rss>
