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.


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.

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

      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.

    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

  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:
Sitecore Marketplace

Content Export Tool:
Sitecore Marketplace

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


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


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.

CET 7.7 – Creating items from Branch Templates with the Import tool

The Content Export Tool has for a while now featured the ability to create items from a CSV import (you can read all about that here). This worked well with regular templates, allowing users to easily simultaneously create and populate the fields of tens or hundreds (maybe thousands, never tried) of items at once. However, it was never tried with branch templates, and as it turns out, branch templates didn’t work.

What is a  branch template?

If you’re familiar with branch templates, you can skip ahead. A branch template is an item that is based off a regular template, but which has pre-made renderings and subitems included. When you create a page with a regular template, it can automatically have renderings and field values assigned to it on creation based on the Standard Values of the template. However, the renderings added in the Standard Values can only point to a pre-existing datasource or no datasource. A branch template can include subitems and have the renderings point to those subitems, and when an item is created from the branch template, all of the subitems are created as well and the renderings on the item can use those subitems as their datasource by default. This allows you to have a pre-formatted template where the content is all unique but the renderings and datasources a created automatically, so you don’t have to manually add every rendering to the page in experience editor.

Creating branch template items with the CET Import

The reason this didn’t work previously was because a branch template is different from a template item, and trying to programatically create a new item with a branch template the same way as with a regular template doesn’t work. It was a simple fix, however, once discovered, and the CET automatically detects whether a template specified in the CSV is a regular or branch template, so nothing has changed for the users. Now, there’s one more question you might have:

What if I want to pre-populate the content of my page, but the fields I need to populate are on the datasource items rather than the page template?

So, you’re using a branch template to create a page. That branch template has one field, “Title”. It also has one component, and the component’s datasource has one field, “Content”. Can you pre-populate the Content field with the CET Import process?

Well… actually no. The reason why you can’t is because the Content Export Tool only allows you to create or edit items with one import. So, if you’re creating a new item from a branch template, you’re going to be using the create option. This means that after the import creates the new item from the branch template, the datasource subitem already exists – you need to edit it, not create it. If you try to include the datasource item in your CSV (which you could do if you correctly predict the path where it is going to be created, which is easy enough), it will either 1) ignore it if you are not allowing duplicate item creation, or 2) create a duplicate item which will have the fields populated, but will not be connected to the rendering (the rendering will still be pointing to the original datasource item).

So the best thing here is to simply run an edit import after you’ve finished your create import. As an additional benefit, since the items already exist at this point, you can use the Export feature to easily generate you CSV for editing, by selecting the newly created item(s) as your starting path(s), selecting the templates of the items you wish to edit (optional), and choosing all fields you want to modify. You can read more here about how to use the Export feature to make your Import CSV easier more easily.

You can download the latest release now from Github; it will be available within the next month on the Sitecore Marketplace.

CET 7.6 – New import features

Version 7.6 of the Content Export Tool introduces some new options to make the Import process even more powerful: the addition of the Update and Delete radios, and the Publish Changes checkbox

new features


These are two new alternative import methods to Create/Update. A quick review of the original items:

Create creates new items at the designated parent path (Item Path column in the CSV). It requires a Name and Template column as well, and any fields that the user wishes to populate.

Update will not create new items but will only modify existing items, designated by Item Path.

There are now two additional import processes:

Publish will publish all of the items in the CSV, designated by path as with the process. The Publish import publishes to the database selected under Publishing Target. This will default to the Web database, if a database named Web exists. Make sure the correct database is selected.


Example use cases:

  1. You previously ran a large import and need to publish all of your changes, but you do not want to publish the common root because that might include changes that aren’t meant to be published yet. The Publish import allows you to publish a large number of items spread anywhere throughout the content tree without having to hunt them down manually, and without the risk that comes with publishing a parent folder.
  2. You modified a bunch of items scattered throughout the tree, but did not publish any of them. Now you need to publish, but as in case 1, do not want to publish the common parent. You can use the Export to get a CSV of all items filtered by Modified Date and Modified By to get all of the items that were modified by yourself within the date range where you were editing items. You can then upload this CSV and run a Publish import to publish all of these items.

Delete will delete all of the items in the CSV, designated by path.

Example use cases:

  1. Similar to case 2 above, you need to delete a large number of items scattered throughout the tree that meet a certain criteria (say, items created by a certain user). Rather than manually finding and deleting every item, you can run an Export with filtering options to get all of the items you want to delete; then upload the CSV and run a Delete import to delete all of them.
  2. You’re running a demo of the Content Export Tool to show off the Import features. You’ve just demoed how awesome the tool is by creating 1000 items scattered through the content tree, and it worked perfectly. But now you need to get rid of all that demo content. You can modify the CSV used for the import to set the correct item paths by appending each item name to the item path and then run the Delete import, or, if you’re not savvy in Excel, run an Export filtering on Created By and Created Date to get the CSV of all the items you just created.

This goes without saying, but be careful with the Delete import! 

Publish Changes

This checkbox will publish items modified in the Create, Update, and Delete imports. It is unnecessary if running a Publish import. When running a Create or  Update import, if Publish Changes is checked, then each item will be published after being edited. If running a Delete import, the item will first be removed from the target database (by having Never Publish set to true and then publishing), and will then be deleted from the master database.

The Publish Changes checkbox publishes to the database selected under Publishing Target.

You can get the latest release of the Content Export Tool on github.

Read more about how to use the Content Export Tool:

Content Export Tool for Sitecore

Why you should use the Sitecore Content Export Tool: A comparison with Sitecore Powershell Extensions

Sitecore Content Importing: Use a CSV file to create or edit Sitecore content

Auditing Sitecore Components with the Content Export/Import Tool

CET 7.0: Packaging Related Items

CET Stories: The Duplicate Field Conundrum

CET: Cascading item creation via CSV import

CET: Cascading item creation via CSV import

One of my colleagues is working on a project where their client needs them to create a large Sitecore subtree for datavisualization, with a folder structure like “year” > “category” > “type” > “data point”. They asked me if they would be able to use the Content Export Tool to accomplish this. I said, “what do you think?” “Well,” they asked, “can it handle creating items that are nested under each other (e.g. parents and children)?” Yes, yes it can. I’ve dubbed this, as of our conversation today, “cascading item creation.”

Cascading item creation is easy. In your CSV file, you can import items of as many different templates as you want in one file. If a field that exists on one template does not exist on another, it will simply be skipped (but you will get a warning at the conclusion of the import, in case you were not expecting the field to be skipped).

Take a look at the CSV in the image below. The CSV is configured to create 12 items. The first two items are Author items; these items are created first because they need to be referenced in the later items. After that, the items are listed in ancestor > descendant order, as you would see them in the Sitecore tree: first I have the Year folder on line 4, then the Category folder, then the articles under that category. For each descendant item, you can see that the Item Path is a path that does not exist yet in Sitecore, but will exist by the time we get to that line. The Item Path is simply the parent item’s Item Path + Name. For example, on line 5 we create a category folder with the name The Content Export Tool under /sitecore/content/Home/Articles/2019, so to create an article under that folder, the Item Path is /sitecore/content/Home/Articles/2019/The Content Export Tool.

CSV used for cascading item creation. Order matters!

In addition to the required columns for creating the items, I have fields from three different templates included in my CSV to populate the fields on my new items as they’re created. I’ve color coded the CSV to designate the different field sections.

Red: Required columns for Import creation.

Blue: Author fields

Orange: Category Folder fields

Yellow: Article fields

What happens if you put the items in the wrong order?

If you were to create an article under path /sitecore/content/Home/Articles/2019/News before you create the News category folder, the parent item (News) will still be created. However, it will be created as a default template item rather than the template you intended (Category Folder). Then, when the line to create the News item is reached, it will be skipped (unless you uncheck “Do Not Create Duplicates”), and any fields that you intended to set on the News item will not be set. If you allow duplicates, it will create the News item and set the fields correctly, but this item will not be the parent of the article you’ve created, but rather another item at the same level as the blank “News” item with no children.

Let’s see it in action!


You probably noticed all the red text after the import. These were the warning lines telling me all of the fields that failed to be set. All of these warnings are expected; because I was importing four different templates and none of them shared any fields in common, each field that did not exist for an item gave me a warning that the field was not found. Not a problem! But it’s good to review the warnings in case there was a mistake made, which would likely be caused by a typo in the field name or an invalid field value.


CET Stories: The Duplicate Field Conundrum

CET Stories  is a series of stories of cases where the Content Export Tool was able to solve problems that otherwise would have required an immense amount of labor. These stories will demonstrate the capabilities of the tool and provide examples of when and why you should use the Content Export Tool. 

I’m not sure how this happened to begin with, but we ran into an issue on one of my sites where a component had a bunch of duplicate fields, and it was causing problems because the author would fill out one field, but it wouldn’t get used because the duplicate field was overriding it. The author could resolve this by making sure that all pairs of duplicate fields had the same value, but this is tedious and shouldn’t need to be done. The simple answer was to remove the duplicate fields, however the template was being used in over 1000 places and the client was very concerned that if I just deleted the duplicate fields, content might get lost if the field that was deleted was the one that had content in it and not the empty one. Which one of the two identical fields was filled out was inconsistent; on one item, FieldName (1) was filled out and FieldName (2) was blank, but on another item (1) was blank and (2) was filled.

There were a grand total of six pairs of duplicate fields. Yikes.

The solution:

I used the Content Export Tool to get a report of every item of that template type, with all six of those fields. Because the duplicates had the same name, I couldn’t select the fields by name (since if I selected FieldName and FieldName, I would only get one field back and the second one would be ignored). Instead, I used the IDs of each field to get the data:


The report it gave me was a little messy, but it worked. All of the data was there, the only issue was that the header row was messed up. The Content Export Tool does not expect different fields to have the same name, so duplicates are ignored. There were twelve columns of data but only six headers.


This was easy enough to parse out though. I could understand the data, but I had to modify the headers in order to be able to re-upload in the Import feature. Even though I input IDs in the export, the CSV displays names instead as that’s more readable for the user, but in this particular case that actually was not what I needed. So I just did some quick edits to put the appropriate field IDs as the headers:


Then I went through my CSV and everywhere FieldName (1) was filled and FieldName (2) was blank (or vice versa), I copied the value into the blank field. Once this was done, I saved my CSV and uploaded it to run the import. I double checked a handful of items and sure enough, all of the duplicate fields now had the same data! We could now delete the duplicate fields from the template and be confident that no content would be lost.