As with many tools and approaches to solving technical issues, you can often find many ways to achieve the same output. The challenge I was up against was how to serve personalized content as JSON when being served from Sitecore.
The solution below is one way you can achieve this, undoubtedly there are many more!
The over-arching setup
Think of your JSON feed like a Sitecore page. You will need to break a rule of REST as Sitecore personalization requires session, and therefore isn’t stateless. This will need to be reflected in your consuming app, if you don’t provide an identifier every request it will need to understand and persist cookies between requests.
First up you need to select a device, a layout and some renderings. None of this differs to normal Sitecore development. I’ve found for debugging purposes using a new device works better as you can view the content as a web page as well as JSON.
The layout
Assuming you’ve decided on a device, you will need to setup a layout:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
@using Sitecore.Analytics @using Sitecore.Analytics.Model.Entities @using Sitecore.Mvc @{ Response.ContentType = "text/javascript"; //note you could easily get the userId from other means e.g. headers / cookies. In fact Querystring isn't great as it shows in path analyzer as different urls. var userId = Request.QueryString["userId"]; if (!String.IsNullOrWhiteSpace(userId)) { if (Tracker.Current != null && Tracker.Current.Session != null) { Tracker.Current.Session.Identify(userId); } } } { @Html.Sitecore().Placeholder("mainjson") } |
The renderings
Again, much like you would for a page, you can create e.g. Controller Renderings which output the content as you need. One thing to note, these will want to render as JSON e.g.:
1 2 3 4 5 6 7 |
@</span><span class="crayon-e">model </span><span class="crayon-v">Website</span><span class="crayon-sy">.</span><span class="crayon-v">Models</span><span class="crayon-sy">.</span><span class="crayon-i">Response</span></div><div class="crayon-line crayon-striped-line" id="crayon-66a0da05892b3502704248-2"> </div><div class="crayon-line" id="crayon-66a0da05892b3502704248-3"><span class="crayon-s">"name"</span><span class="crayon-o">:</span><span class="crayon-s">"@Model.Name"span><span class="crayon-sy">,</span></div><div class="crayon-line crayon-striped-line" id="crayon-66a0da05892b3502704248-4"><span class="crayon-s">"content"</span><span class="crayon-o">:</span><span class="crayon-s">"@Model.Text"</span><span class="crayon-sy">,</span></div><div class="crayon-line" id="crayon-66a0da05892b3502704248-5"><span class="crayon-s">"variation"</span><span class="crayon-o">:</span><span class="crayon-s">"@Model.Variation",</span></div> |
These components can have datasources setup as normal, and hence personalization is available into your JSON feed.
Via a browser you would then load the url as normal, remembering to specify the device you’ve selected and you should see content based off rules, user information and behaviours and more.
Taking it to the next level
The simpler approach assumes you have one component per page. Complexity comes in when you need to generate valid JSON based off multiple controls – this can be achieved but requires you to either configure things via rendering parameters or at the point the page is rendered, interrogate the counterpart presentation components and work out whether you have sibling controls.
If you find you have sibling components to render you’d need to add commas after your controls to ensure valid JSON.