Migrating Content to Sitecore: From CSV to Sitecore Packages

From Excel to Sitecore: a step-by-step content migration guide.

March 11, 2025

By Anju Thomas

Content Migration Using Scripts

A recent project required the migration of specific content to a new Sitecore instance. The task involved processing an Excel sheet containing item IDs designated for migration. While the objective appeared straightforward, it necessitated a methodical and efficient approach to ensure accuracy and reliability. Here’s the process I followed.

The first step was to make the Excel file accessible within the Sitecore environment. To achieve this, the file was converted into a CSV format and uploaded to the Media Library in a designated folder.

Subsequently, a PowerShell script was developed to automate the process. This script iterated through each row of the CSV file, retrieved the item IDs, fetched the corresponding items from Sitecore, and added them to the package source. In my case the requirement was for migrating a few blogs from an old Sitecore instance to our new QA environment.

PowerShell Script for Content Migration

# Configuration
$mediaItemPath = "/sitecore/media library/script/blog-migration"
$packageName = "Blog-Items-Package"
$packageVersion = "1.0"
$packageAuthor = "Anju Thomas"

try {
    Write-Host "Creating package & metadata..."
    # Create and configure package
    $package = New-Package $packageName
    $package.Sources.Clear()
    $package.Metadata.Author = $packageAuthor
    $package.Metadata.Version = $packageVersion
    $package.Metadata.Readme = "Package containing items from CSV file"

    # Get media item
    $mediaItem = Get-Item -Path $mediaItemPath -Language "en" -ErrorAction Stop
    if (-not $mediaItem) {
        throw "Media item not found at path: $mediaItemPath"
    }
    Write-Host "Processing CSV file..."
    # Get media stream and create temporary file
    $mediaStream = [Sitecore.Resources.Media.MediaManager]::GetMedia([Sitecore.Data.Items.MediaItem]$mediaItem).GetStream().Stream
    $tempFilePath = [System.IO.Path]::GetTempFileName()

    # Process items in a bulk context for better performance
    New-UsingBlock (New-Object Sitecore.Data.BulkUpdateContext) {
        # Copy stream to temp file
        $fileStream = [System.IO.File]::Create($tempFilePath)
        $mediaStream.CopyTo($fileStream)
        $fileStream.Close()

        # Read and process CSV
        $importList = Import-Csv -Path $tempFilePath
        $totalItems = $importList.Count
        $processedItems = 0

        foreach ($row in $importList) {
            $processedItems++
            Write-Progress -Activity "Processing Items" -Status "Processing item $processedItems of $totalItems" -PercentComplete (($processedItems / $totalItems) * 100)

            try {
                $item = Get-Item -Path "master:" -ID $row.ID -ErrorAction Stop
                if ($item) {
                    Write-Host "Adding item to package: $($item.Name) ($($row.ID))"
                    $source = $item | New-ItemSource -Name $item.Name -InstallMode Overwrite
                    $package.Sources.Add($source)
                }
            }
            catch {
                Write-Warning "Could not find item with ID: $($row.ID)"
            }
        }
    }

    Write-Host "Exporting package..."
    # Export package
    $packagePath = "$($package.Name)-$($package.Metadata.Version).zip"
    Export-Package -Project $package -Path $packagePath -Zip

    # Offer download
    Write-Host "Package created successfully. Initiating download..."
    Download-File "$SitecorePackageFolder\$packagePath"
}
catch {
    Write-Error "An error occurred: $_"
    throw
}
finally {
    # Cleanup
    if ($null -ne $mediaStream) { $mediaStream.Dispose() }
    if ($null -ne $fileStream) { $fileStream.Dispose() }
    if (Test-Path $tempFilePath) { Remove-Item $tempFilePath -Force }
}

Script Highlights

Package Metadata

The script begins by initializing a new Sitecore package with essential metadata, including the package name, version, and author.

Retrieving the CSV File

Next, the script fetches the CSV file stored in the Media Library using a specified path. The file is then copied to a temporary location for further processing.

Bulk Processing

To handle items efficiently, the script uses the BulkUpdateContext. It reads each row from the CSV file and retrieves the corresponding item from the Sitecore database using the provided ID.

Adding Items to the Package

For each valid item retrieved, the script adds it to the package source. The items are added with an 'Overwrite' installation mode, so during installation, it doesn’t prompt for an action each time.

Exporting the Package

Once all items have been added, the script exports the package as a ZIP file. This file is then ready for download and could be installed in the target environment.

Cleanup

Finally, the script disposes of temporary files and streams to prevent memory leaks and ensure no lingering temporary data remains.

At the end of the process, the package is ready for download, as shown in the screenshot.

Screenshot of Sitecore package ready for download

Content Migration Simplified

This script simplifies Sitecore content migration when you have a list of items to transfer. It can easily be adapted to fetch related items for each blog, ensuring that all associated media mentioned in fields are also included in the migration package. This flexibility makes the script a powerful tool for comprehensive content migrations.

Anju Headshot

Anju Thomas

Sitecore Web Developer

Anju is a Sitecore Developer with a Bachelor's Degree in Computer Science and over 4 years of experience in Sitecore development. She loves solving Sudoku puzzles, watching movies, eating delicious food and exploring the world.