Displaying a Custom Facebook Feed in .NET Using the Facebook SDK

There are many ways to display your business’s Facebook feed within your website, and the amount of documentation out there covering the numerous methods can make it difficult to know where to start. You can embed your feed using the very straight-forward Facebook plugin – this page allows you to configure your feed to the settings you want and then generates the code for you so all you need to do is paste it into your codebase, and there plenty of third-party options as well. However, if you’re looking to have more control over the display of your feed, you probably want to use the Facebook Open Graph API to retrieve your feed as a data model in your code, and then you can display it however you want. However, the documentation on doing so is so extensive that it can be pretty overwhelming, and you have to look through many pages to get what you need. In this post I’m going to put together one consolidated guide that will help you set up your Facebook developer account, get the data you need to access the API (access token, page ID, etc), and the C# code to implement it.

Facebook Setup – getting your App Id, Page Id, and Access Token

The first thing you need to do is create your Facebook developer app. If you already have a developer app, you can skip ahead

Create the developer app

  1. Go to https://developers.facebook.com/ and choose Create App under the My Apps menu.
  2. On the Add a Product page, select Facebook Login > WWW
  3. Go through the setup here – all you really need to do is put in the URL of your website

Get an Access Token and Set Permissions

  1. Under the Tools menu, go to Graph API Explorer
  2. On the right side bar, under Facebook App, select the app you just created
  3. In the User or Page menu, do the following:
    1. Click Get User Access Token
    2. Click Get Page Access Token
      1. This will ask you which Facebook pages you want to associate with this app
    3. If you intend to display Instagram in your site as well, add the instagram_basic permission
  4. Now you have your Short Term Access Token (in the top of the right bar) – copy this somewhere
  5. With User Token selected, paste the following into the query bar at the top of the page and click Submit: me?fields=id,name
    query
  6. Copy the id returned in the body of the query – This is your Page ID

Get a Long-Lived Access Token

The Access Token that you got in the last section is only good for one hour. You need to exchange it for a Long-Lived Access Token, which lasts 60 days.

  1. Go to your app > Settings > Basic and copy the App ID and App Secret
  2. make a request (using Curl or Postman, for example) to “https://graph.facebook.com/{graph-api-version}/oauth/access_token? grant_type=fb_exchange_token& client_id={app-id}& client_secret={app-secret}& fb_exchange_token={your-access-token}”

This will give you your long-lived access token. This is the one you want to use going forward.

You can debug and view your token information at https://developers.facebook.com/tools/debug/accesstoken/?access_token={access_token}

Code Integration – time to use those values from the last section

In the previous section, we got the Access Token and Page ID.

  1. Install the Facebook SDK. You can get this from the Nuget Package Manager – it’s just called “Facebook”
  2. Here is the code that gets the Facebook feed data, using the FacebookClient
    facebook code

You can see that the code is basically just doing the same thing as if you were to make an WebRequest to the Open Graph API; the Facebook SDK just makes it more simple. However if you don’t want to use the Facebook SDK, you can make this call however you want (through a WebRequest, Ajax, etc). You got your Page ID in the previous step; in the Graph Explorer, run the query {page_id}/posts?fields={fields}. Include all fields you want – once you type “fields=” it will show autosuggestions of all the fields available.

Once you’ve created your query with all the fields you want, click the Get Code button at the bottom of the window. This will give you example code in a number of languages, but what I like the most is the cURL section at the end, because this gives you the complete URL you need (with all parameters already filled out – page id, access token, fields) to make your GET request, however you with to do it.

To make this easier to update on the fly, I recommend creating fields in Sitecore to store the Access Token and Page ID, so that you can update them any time.

One Last Thing… Instagram!

Facebook owns Instagram now, and once you’ve gone through all the setup above, it’s super easy to integrate your Instagram feed into your code as well. All you need to get is your Instagram Business Account Id

  1. In the Graph API Explorer, under User or Page select your page.
  2. Run this query: me?fields=instagram_business_account
  3. This will give you your Business Account ID.

The API path to get your instagram posts is {business_account_id}/media. This will give you a list of all your posts; make sure to add ?fields={whatever fields you want}. You can use the Get Code button to get the GET url for your query, or follow the example of C# code below – you’ll notice it’s very similar to the one for the Facebook feed, the only differences are:

  1. userId is now the Business Account ID, not the Facebook user ID or page ID.
  2. The path is now {userId}/media
  3. We’re requesting different fields

instagram code

The Vital Importance of Good Branching

Even the best laid plans go awry been bad branching occurs.

I’m going to start off by assuming you know what branching is and are somewhat familiar with Github/source control. The reason why branches are important is because they allow one or more developers to do development work for multiple independent projects simultaneously, and as long as each project is done in a unique branch, that project can be merged back into the master branch and deployed to production without  deploying any other projects – therefore, if the projects are not dependent on each other, you can deploy them individually as they’re finished rather than waiting for every single one to be completed, and if there’s a problem with one, you can revert it without reverting the others. Branches can allow multiple devs to each work on their own projects simultaneously without affecting each other’s code, but a solo dev should also use multiple branches if they are working on multiple different projects at once that don’t need to be dependent on each other.

However, the benefits of branching are lost of improper branching is done, and in fact, branching mistakes can cause major problems and can be worse than if every project was done (knowingly) in one single branch to begin with. It’s vitally important to practice good branching strategy and make sure all devs are on the same page, because if  a project branch is created off the wrong branch or has the wrong branch merged into it, you can end up deploying code that’s not supposed to be deployed without even realizing it. Here’s a story of that happening.

The disaster

My role, as a support developer, is to handle ongoing maintenance and development work for my clients, including fixing bugs, making improvements, and creating new components for the site. However, our support contract is limited to a monthly cap, so when the client wants a big project to be done that doesn’t fit within the support budget, we usually write a new project contract and have a separate team complete the project while I continue to do my support work. We often have multiple projects ongoing at the same time.

“Bob” was a contractor working on a contract for a project, Project A, for one of my clients. Bob was a really good developer – he wrote good code, it worked, it made the client happy, they were ready to deploy it to production.

The problem, as we discovered after deploying, was that Bob had rebased the Dev branch into his project branch.

Remember how I mentioned there were multiple projects occurring simultaneously? The Dev branch is an environmental branch, which is deployed to dev.website.com, where all of the project code is reviewed and tested as it’s completed. The Dev branch contained all of the project work that was completed, in-progress, waiting for testing, etc. It included Project B, which was still in the works and had not been approved to be deployed yet, and it included all of my support work, much of which was waiting to be tested and approved.

The ProjectA branch, in a world without mistakes, would have been an exact copy of Master plus the code changes for Project A, and JUST the code changes for Project A. But because Bob had rebased Dev into ProjectA (rebasing is essentially the same as merging but much harder to track), ProjectA contained every other branch that had been merged into Dev at that time, including the entire ProjectB branch and all of my support work. So rather than just deploying Project A, we unknowingly deployed everything that was in Dev, including a whole lot of code that wasn’t tested or wasn’t yet approved to be deployed.

This caused a big problem because Project B introduced a bug that had not yet been discovered, but likely would have been discovered in our testing process prior to (intentionally) deploying Project B. This bug broke site login for a number of users – and some of these users were premier users who paid a lot each month for their site membership. Because this bug was live and we had to resolve it ASAP, we had to locate which code specifically belonged to Project B (which was challenging, since as I mentioned there is not a lot of tracking with rebases and it was not very apparent in the Git History which file changes came from which branches), and revert that code. It would have been easier and safer to revert the entire deployment, but the client was strongly opposed to this, as Project A had been a huge project and the client didn’t want to revert all of the site improvements we had just deployed. So, we had to carefully review the several hundred files that had been merged into master, identify which ones belonged to Project B and revert just those files. I was wary of this, because it was a risky way to do things — if we missed one file from Project B, it could have broken things even worse if we now had one modified file from Project B that depended on other Project B changes which were now gone. In the end, we succeeded in pulling out just Project B, and it could have been a lot worse — I’ve done work for clients where they’ve had specific, legal reasons for not deploying new code before a particular date, and if something like that were to happen where a major change went live before it was supposed to due to bad branching, the clients would be justifiable very upset.

How to avoid calamity

The first important thing is to have an established branching strategy. In my department, we have the following branching strategy and rules:

a02e2666-a61e-43b0-848d-2059cc77044b
Branching flow
  1. For all new projects/tickets, create a new branch off of Master
    1. If Project B is dependent on Project A, in that case you can branch off of ProjectA but make it clear that ProjectB is a sub-branch of ProjectA (or wait until ProjectA has been deployed into Master and then branch off of Master)
    2. NEVER branch off of an environment branch (Dev, UAT) other than Master for a new project
  2. NEVER merge an environment branch (Dev, UAT) other than Master into your project branch*
    1. *Technically it can be OK to merge Regression into your project but only if Regression is fully up to date with Master already. It’s Dev/Support/UAT that tend to have untested/unfinished/unapproved project work in them, so those are the branches you absolutely cannot merge.
  3. To promote your project branch through the environments:
    1. Merge your project branch directly into your testing environment (Dev, Support, whatever you call it)
    2. Merge your project branch directly into the UAT environment (if you have a separate UAT environment)
    3. Merge your project branch directly into the Regression environment. Test regression to make sure all branches have been merged in correctly and there are no side-effects
    4. Merge Regression directly into Master
      1. The reason for merging project branches into Regression and then Regression into Master, rather than merging project branches directly into Master, is because this gives you the ability to resolve merge conflicts, test that everything has been merged correctly, and test the environment to catch any new bugs before merging into Master. If there are merge conflicts between your branches, they get resolved in Regression and once it’s time to deploy to Master you only have to merge the single Regression branch in with no conflicts to resolve.
  4. Did I mention NEVER merge an environment branch into your project branch?
do not
Don’t

The next important thing after having a branching strategy is to make sure everyone knows it. We’ve run into trouble at my company because although my department has a solid strategy, we have had contractors cause issues like the one in the story above because they are not familiar with the branching strategy, or don’t appreciate the importance of it. Reviewing the branching strategy should be a critical part of onboarding any new developer, because a branching strategy is only good if every developer on the project is using it.

You don’t have to use the same strategy as the one I shared above, but have strategy. You may only have one environment for dev, testing, and UAT. You may not have a regression environment. All of the steps involved in our branching strategy exist to catch bugs and merging errors, but you can get away with a simpler workflow if needed. The most important thing is to have all devs be aware of which branches contain what code, which branches are safe to branch off of… and to never ever merge or rebase Dev into your project branch.

 

CET 8.1: Deletions Audit

Update 8.1 of the Content Export Tool adds a new feature in the Special Audits section, the Deletions Audit:

deletions audit

The Deletions Audit is a simple audit that reports the items in the Recycle Bin, providing each item’s path, ID, and date deleted.

output

The main benefit of the Deletions Audit is that it serves as a way to “package” deletions to promote them to another environment.

For example, suppose you have made a lot of content changes in a testing environment which involves deleting obsolete items and making sure nothing breaks in the test environment. Now you need to delete all the same items on production, but you’ve deleted a whole bunch of items and don’t remember exactly what was changed.

Using the Deletions Audit, you can get a list of all of the items in the Recycle Bin that were deleted by you (“My Deleted Items” option) within the date range when you were making your changes. Review the CSV and make sure to remove any line items that aren’t actually related to the changes you intend to promote. Then, on prod, upload Deletions Export.csv in the Import section, select the Delete option, and run the import.

deletions import

This will delete each item in the CSV based on the Item Path column; if the item does not exist in that environment, that line will be skipped but the Deletion Import will continue to the next line.

Version 8.1 can be downloaded on Github.

SEO friendly URL masking for bucketed Sitecore items – making a custom item resolver and link provider

Item buckets allow for a large number of items to be stored in the Sitecore content tree, and many modules, such as WeBlog, implement bucketing to store content in a logically organized manner – for example, by automatically placing them into subfolders by year and date (e.g. /blog/2020/1/new-blog-post). This automatic organization is helpful for finding content, and the bucketing helps alleviate performance issues that occur with a huge amount of content, but the resulting URLs are not great, for the following reasons:

  1. They are not very SEO friendly
  2. They are not very user friendly – users cannot easily remember or guess a URL that includes date-based segments like “/blog/2020/1/new-blog-post”, as opposed to intuitive URLs like “/blog/new-blog-post”
  3. Although a page that is months or years old may still be highly relevant, having the URL reveal that it is old may make the users think that it is stale content. Hiding the date segments from the URL will help avoid bias against old content.

There are two main steps to implementing friendly URL masking. For the purpose of this article I will discuss masking items with the Article taxonomy under /content/articles, but keep in mind that you can implement URL masking for any type of content and under any root path. However, the broader your masking — that is, if you choose not to filter by a Template or Taxonomy and/or choose not to restrict masking to a particular folder — you are more likely to run into problems with your Item Resolver returning the wrong item.

1. Custom Item Resolver – Resolve friendly URLs to the matching Sitecore item

The first step is to create a custom item resolver. This is a HttpRequestProcessor that is patched after the Sitecore ItemResolver Pipeline. The goal of our custom item resolver is, if no item has already been found at the requested path, to find the item (using Sitecore search) whose name matches the last part of the URL.

item resolver.PNG

Let’s dissect the code above.

First, if Sitecore.Context.Item is not null, we exit out of the custom processor.

Next, we take a look at the requested URL. In my code, I am only trying to mask content under /content/articles, so if the requested path does not start with that path, I exit the processor.

I then get the requested item name, which is the last part of the path. I replace all hyphens with spaces and transform it to lowercase.

Finally, I use Sitecore search to find results where the Content Type taxonomy (“contenttype” in my Index) equals “Article” and where “searchname” equals the transformed item name.

customsearchresult.PNG

But wait, what’s searchname? Because I did not want to have to worry about case sensitivity or items where the item name actually contains hyphens, I made a computed field called “searchname”. The computed field simple takes the item name, replaces all hyphens with spaces, and converts to lowercase. I did this because Sitecore search does not allow me to do transformations within the Query predicate — that is, this line below throws an error:

var query = searchContext.GetQueryable<CustomSearchResult>().Where(x => x.ContentType == "Article" && x.Name.ToLower().Replace("-", " ") == articleName);

Therefore, my string transformations have be done when the item is indexed, and I search against the computed field.

computed field.PNG

2. Custom Link Provider – generate friendly links to blog pages within the site

With the custom item resolver, /content/articles/seo-friendly-urls will resolve to the item /content/articles/2020/january/seo-friendly-urls, but the internal links within our site that point to our Seo Friendly Urls article (e.g. URLs on the search results page, URLs generated by Link fields) will still appear as /content/articles/2020/january/seo-friendly-urls and will resolve to the full URL — the custom item resolver takes friendly URLs and finds the associated content item, but does nothing to change unfriendly URLs (remember, if Sitecore.Context.Item is not null, the item resolver does nothing).

To make sure all of the links to the article pages within your site use the friendly URL as well, we need to create a custom link provider.

custom link provider.PNG

In the code above, you can see that if the current item is NOT an article under our “/content/articles” path, we use the base Sitecore method to get the item URL. However, if we have an article, we take the item name and generate a URL that correlates to our masked URLs from step one (notice how inversely to step one, in this step we replace spaces with hyphens to create a friendly URL that our custom item resolver can process).

The last step is to patch in your custom item resolver and link provider:

patch.PNG

That’s it! Your link provider will generate your item links as friendly URLs, and your item resolver will resolve those friendly URLs into the associated item! One thing to note – you may have caught this, but the item resolver will fail if multiple Article items under /content/articles have the same name. It uses Sitecore search to get the first Article item whose name matches, so if there is more than one item that matches, that’s a problem. Keep that in mind when naming your items if you are using or plan to implement URL masking.

Accelerating WFFM-to-Sitecore-Forms Migrations with the WFFM Conversion Tool and Content Export Tool

Sitecore Web Forms For Marketers (WFFM) was officially deprecated with the release of Sitecore XP 9.1, replaced by Sitecore Forms. While this was no issue for brand new website development, this was a huge pain point for Sitecore users who currently had an 8.2 or lower site and wanted to upgrade to Sitecore 9. Sitecore offered no out-of-the-box solution for migrating WFFM to Sitecore Forms, so the only option was to manually recreate all WFFM forms as Sitecore Forms. Now, I have a few clients whose websites are largely form-driven and as such, they have hundreds of forms, and manually recreating every one posed a tedious and time-consuming task. Fortunately, there are two modules that now exist that can make form migrations a breeze: the WFFM Conversion Tool and the Content Export Tool. I’ll explain what each does, and how we used the two together to drastically accelerate a site migration.

The WFFM Conversion Tool, created by Alessandro Faniuolo, is an open source console application that automatically converts WFFM forms in your old solution into Sitecore Forms in your new solution, and migrates the form data as well so that previously collected data is not lost. I won’t go into extensive detail here, but you can read more about it on his blog. The important thing to know is that is that if you’re upgrading to Sitecore 9.1+ and need to migrate forms, this is the tool to use.

However, your new Sitecore 9 forms may not be quite finished yet, and this is where the Content Export Tool comes into play. If you’re converting WFFM to Sitecore 9 forms, there may be some style or formatting changes you need to make, such as adding new CSS classes or making structural changes such as wrapping field items in form sections.

The Content Export Tool’s Import feature can be used to modify the CSS classes on hundreds of form items in a matter of minutes. You can read the full details on content importing here, but here’s the short version of how to modify the fields in bulk:

  1. Run an Export to get all form items with the Css Class field. This is a very simple export: just set Start Item to “/sitecore/Forms” and Fields to “Css Class”
  2. Open up the exported CSV file and fill out the Css Class column to set the class on every item you need. You can delete line items you don’t need to update, but you can also just ignore them — if the Css Class isn’t changed, then no change will be made in Sitecore, so there’s no risk to including lines that haven’t been modified.
  3. Run the Content Import with Update selected.
    import css.PNG
  4. Publish your forms — or, if you checked off “Publish changes” before you ran the import, you’re already done.

As you can see, setting Css Classes in bulk is super easy. Making structural changes is a bit more complicated. For this example, we need to wrap one specific form field, the Name input field, in a Section.

  1. Run a content export to get all of the Input field items under /sitecore/Forms, with ALL of their field values:
    1. Start Path: /sitecore/Forms
    2. Template: /sitecore/templates/System/Forms/Fields/Input
    3. All Fields: true

      output
      An example of the exported CSV data
  2. Now you need to do some Excel work. Modify your CSV file to get rid of all of the line items you don’t want. In this case, I want to wrap every Name field on every form in a section, but I don’t want to modify anything else, so I’m going to modify my CSV to get rid of every line where Title does not equal “Name”. I did this by sorting on the Title column A-Z, and then deleting all lines above and below those where Title = Name, but I’m not an Excel expert so there are probably easier ways to do this.

    filtered.PNG
    Modified CSV. In this example I don’t have a ton of Name items, but let’s pretend there are a lot more lines here.
  3. Create a new CSV file.
  4. Copy the Item Path column from the export to the blank CSV.
    item path.PNG
  5. On every row, remove the last part of the item path (e.g. “/sitecore/Forms/SignUp/Page/Name” > “/sitecore/Forms/SignUp/Page”
    updated path.PNG
  6. Add the Template and Name columns and fill them out. Template will be “/sitecore/templates/System/Forms/Fields/Section” but Name can be anything
    template and name.PNG
  7.  Now you’re ready to run the Import. Save and upload the new CSV and select Create.
  8. Now we’re going to create another new file. This time, copy all of the contents of the original file (we still want to keep our original file intact for our final step).
  9. Modify the Item Path on every line – we’re going to replace the last part of the path, which is currently our Field item name, with the new Section item name.
    updated paths.PNG
  10. Add the Template and Name columns. Template is “/sitecore/templates/System/Forms/Fields/Input”; name can be anything, but I’m just going to call them all “Name”
    template and name new.PNG
  11. Run the import. We’re using Create again. This will create all of our new Name Input items under our new Section items, and will populate all of the field values to match the original Name input items.
  12. Lastly, we need to delete the old Name input items. This is why we kept our original export CSV unchanged – because it already has the full list of item paths we need to delete. If you modified this file directly and changed the paths to do the second import, that’s ok, you just need to repeat steps 1 and 2 to recreate the CSV with all the original items paths, or modify the paths again to set them back to the original paths.

    Upload your CSV with all of the original item paths, select Delete, and run the import
    delete.PNG

  13. Review your changes and publish your forms.

The limitation of this process is that you can’t control where under the parent the Section item gets created, and if you have multiple field items, it’s likely that the Section won’t be placed in the same position where the Name field was (it will likely either be created as the last item under its parent, or put in alphabetical order). So, you’ll want to go through your forms and move the new Section item to the correct position as needed.

Here’s a testimonial from my colleague Matt Richardson, who used the processes above to save a ton of time and work in a site upgrade — he’s the one who figured out how to use the tool for the item-wrapping process and shared his method with me.

I used the Content Export Tool to update field values quickly on over 80 Sitecore forms and their sub-items. Multiple different value changes needed to be made to hundreds of fields over more than 80 forms. The Content Export Tool was exceptionally useful in this scenario because a specific set of fields and their values, tied to the value of another field on the item, needed to be updated where updating Standard Values would’ve updated all of them. We were looking to apply CSS classes to this specific subset of Forms items. I was able to use the filters available on through the tool to target just the items I needed to change, export just the field values I needed to change, update the values quickly in the CSV, and then upload the updated CSV to update the field values for all those items. Doing the change by hand would’ve required at least several hours and greatly increased the risk of a mistake. I subsequently used the tool to make structure changes to the forms. We had a specific Form field type that needed to be wrapped in a Forms Section. I used the tool to create the new sections (create), create duplicate items under the new section (move), and remove the old items (delete).

The WFFM Conversion Tool and the Content Export Tool are both available on the Sitecore Marketplace and Github. If you’ve found them helpful, please rate them on the Marketplace; if you found a creative way to use the Content Export Tool that I haven’t previously discussed, please share it with me!

WFFM Conversion Tool:
Github
Sitecore Marketplace

Content Export Tool:
Github
Sitecore Marketplace

Setting up a Sitecore RSS Feed – things you might have missed

The Sitecore documentation provides straightforward instructions on how to set up an RSS feed. It guides you through creating your RSS feed item and configuring field mappings so that items can be listed in the feed. This is everything you need to get it working – theoretically – but there are a few additional steps you may need to take once you get to your prod environment.

Allowing anonymous access to the /sitecore/feeds folder

After you publish your RSS feed item and browse to the feed, you may encounter this page:

access denied.png

The Sitecore RSS feed mechanism is stored in the /sitecore/shell/applications/feeds and sitecore/shell/Feeds folders, and if anonymous users are denied access to /sitecore/shell (which they should be!), they won’t be able to access these folders and will get this error. You may have missed this when testing it locally because if you are not testing in a CD/CM environment, you were probably still logged in as an authenticated user when you browsed to the feed.

To allow access, add this to your web.config:

<location path="sitecore/shell/feeds">
  <system.web>
    <authorization>
      <allow users="?" />
    </authorization>
  </system.web>
</location>
<location path="sitecore/shell/applications/feeds">
  <system.web>
    <authorization>
      <allow users="?" />
    </authorization>
  </system.web>
</location>

There are no fields available to map for the Title

no titles

The RSS feed only supports plain text fields, e.g. Single-Line Text or Multiline text. If your title fields are Rich Text, they will not be available to map to the Title field. You will need to either change these fields to single or multiline text (which could be risky, as if any of the existing fields contain HTML, this HTML will break the RSS feed); or create a new plain-text title field.

Note: If you choose to create a new plain-text title field, but are concerned about having to fill it out for hundreds of items, you can use the Content Export Tool to export all of the rich-text title field values, strip out any HTML and change the field name to the new plain-text field, and upload to instantly populate the new title field on every item.

CET 8.0 – Modifying Sitecore Rendering Parameters with the Content Export Tool

Recently I have had to write a few import scripts to do bulk modification to rendering parameters, so I have added the capability to the Content Export Tool. Below I will explain the new Rendering Parameters Import feature; explain the two scenarios in which I needed to modify rendering parameters in bulk; and how each scenario is accomplished with the Content Export Tool.

It is recommended that the Rendering Parameters Import is used by developers rather than content authors, as it requires a somewhat more technical understanding of Sitecore than the Content Import.

rendering parameters import

How to use the Rendering Parameters Import

As with Content Import, this import is done using a CSV file. The Rendering Parameters Import can do the following:

  • Change the placeholder of a rendering
  • Change the value of a rendering parameter field on a specific rendering
  • Change the position of a rendering (relative to all other renderings, or relative to the placeholder it is in)
  • Move the rendering before or after another rendering

The above functions are accomplished using the following CSV headers:

  • Item Path This column should contain the item path or ID. 
  • Apply to All Subitems Apply the changes on this line to the item and all subitems, defaults to false (TRUE/FALSE)
  • Template With Apply to All Subitems, apply the changes only to items with the specified template name or ID. This field is ignored when Apply to All Subitems is not true
  • Component Name The name or ID of the component to modify. If this is not specified, no changes will be made
  • When Placeholder Equals Modify a component within this particular placeholder
  • Nth of Type Modify the Nth component with the specified name (NUMERIC, STARTS AT 1)
    • With When Placeholder Equals, modify the Nth component within the specified placeholder with the specified name
  • Parameter Name The name of the rendering parameter to modify or add
  • Value The value to set for the rendering parameter
  • Placeholder The placeholder to move the rendering to
  • Position The position to put the rendering in relative to all other renderings (NUMERIC, STARTS AT 0)
  • Position in Placeholder The position to put the rendering in relative to its placeholder (NUMERIC, STARTS AT 0)
  • Before The name of the FIRST rendering to put this rendering before
  • After The name of the LAST rendering to put this rendering after

By default changes will be made to the first rendering that matches the requirements (i.e. matches Component Name and optional When Placeholder Equals). However, if you wish to target a rendering other than the first, you can use the Nth of Type header. For example, if you have three instances of the Rich Text component in the MainContent placeholder, you can target the second one by setting When Placeholder Equals to “MainContent” and Nth of Type to “2” (note: Nth of Type starts at 1, but Position and Position in Placeholder start at 0).

As with the Content Import, you can automatically publish all modified items by checking off the Publish Changes checkbox.

Example 1: Change the value of a rendering parameter

The first issue that occurred was when a client had me add a new rendering parameter field to a dynamic content listing component. The new field was a checkbox field called “Show Subtitle”. After this was created, they needed help because they needed “Show Subtitle” to be checked off on hundreds of pages… but not on EVERY instance of the component, only on the pages in a specific folder. So, I couldn’t easily check off “Show Subtitle” for every instance with the Standard Values; I had to modify them programatically, or else deal with a very tedious manual process.

How to do it:

This import only requires on line in the CSV, with the following values:

  1. Item Path: /sitecore/content/home/NewsListings (the folder where I needed to modify all items)
  2. Apply to Subitems: TRUE
  3. Template: News Listing Page (only modify pages of the particular template)
  4. Component Name: Dynamic Content Listing
  5. Parameter Name: Show Subtitle
  6. Value: 1

CSV

I uploaded the file and checked Publish Changes so that I could publish all of the modified pages without manually publishing the root folder, which would risk publishing changes that weren’t intended to be published yet.

Example 2: Change the placeholder of a rendering

The second issue was that the client had hundreds of pages of a particular template (Article Page) on their site, and they decided that they didn’t like the position of a particular component (the metadata component, which showed the date published and the author). They wanted it moved from the side of the page to the top content, beneath the Page Header and above the Social Share Bar.

This couldn’t be done with a simple CSS or HTML code change, because the metadata was a component on the page and the place it showed up was based on its placeholder (although technically it could maybe have been moved with CSS, it would have been hacky and not the right way to go about fixing it). So, I needed to update the placeholder and make sure it came before the Social Share Bar. Once again, with hundreds of pages to update, this would have been extremely tedious to do manually.

How to do it:

This import again only requires on line in the CSV, with the following values:

  1. Item Path: /sitecore/content/home/Articles
  2. Apply to Subitems: TRUE
  3. Template: Article Page
  4. When Placeholder Equals: Main Content Left Column
  5. Component Name: Page Metadata
  6. Placeholder: Header Content
  7. Before: Social Share Bar

example 2.PNG

The reason I used When Placeholder Equals is because I only wanted to move the Page Metadata when it was in the Main Content Left Column placeholder. If it was already in the header, or somewhere else on the page, I didn’t want to risk modifying it since it was either already in the right place, or somewhere else intentionally.

When run, this import moved the

Considerations:

The examples I provided were cases where only one instance of the component I needed to modify existed on each page. The import gets more difficult if, say, there are three Page Metadata components on the page; you will need to make sure to target the correct one, and use Nth of Type and/or When Placeholder Equals if you wish to modify other than the first one.

This consideration also applies to Before and After; if there were, say, three Social Share Bar components, Before would place the Page Metadata before the first Social Share Bar; After would place the Page Metadata after the last Social Share Bar.

One thing the import currently does not offer is the option to modify ALL matching components; you will have to add a new line with a different value for Nth of Type to update all instances of the component.

I recommend practicing the Rendering Parameters Import on some test items before making changes to real items. As always, use caution, especially when Publish Changes is checked, as this import can mess up your content if mistakes are made in the CSV.

You can download the new release on Github.