ImportAssetToOptiDam 1.0.1

dotnet add package ImportAssetToOptiDam --version 1.0.1
                    
NuGet\Install-Package ImportAssetToOptiDam -Version 1.0.1
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="ImportAssetToOptiDam" Version="1.0.1" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="ImportAssetToOptiDam" Version="1.0.1" />
                    
Directory.Packages.props
<PackageReference Include="ImportAssetToOptiDam" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add ImportAssetToOptiDam --version 1.0.1
                    
#r "nuget: ImportAssetToOptiDam, 1.0.1"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package ImportAssetToOptiDam@1.0.1
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=ImportAssetToOptiDam&version=1.0.1
                    
Install as a Cake Addin
#tool nuget:?package=ImportAssetToOptiDam&version=1.0.1
                    
Install as a Cake Tool

ImportAssetToOptiDam

Console utility that bulk-imports assets listed in an Excel spreadsheet into the Optimizely CMP DAM.

It:

  • Reads each row from Excel.
  • Uploads the corresponding file.
  • Registers it as an asset.
  • Updates metadata such as title, description, alt text, and tags.
  • Applies custom DAM fields based on column headers.
  • Generates an output Excel report with published DAM URLs.

Features

  • Bulk upload assets using Excel.
  • Metadata-driven import for tags, attributes, and SEO fields.
  • Supports custom DAM fields by matching spreadsheet column headers to DAM field names.
  • Generates an output report with publish URLs.
  • Does not require direct CMP UI access for the import run.

Prerequisites

  • .NET SDK 8.0 or later.
  • Optimizely CMP app credentials: Client ID and Client Secret.

Configuration

All configuration is defined in appsettings.json.

Setting Credentials

For local development, replace the placeholder values in appsettings.json:

{
  "OptimizelyCmp": {
    "BaseUrl": "https://api.cmp.optimizely.com",
    "TokenUrl": "https://accounts.cmp.optimizely.com/o/oauth2/v1/token",
    "ApiVersion": "v3",
    "ClientId": "REPLACE_WITH_CLIENT_ID",
    "ClientSecret": "REPLACE_WITH_CLIENT_SECRET",
    "TokenRefreshSkewSeconds": 60,
    "FieldsPageSize": 100
  }
}

For safer local development, use .NET user secrets:

cd ImportAssetToOptiDam
dotnet user-secrets init
dotnet user-secrets set "OptimizelyCmp:ClientId" "<your-client-id>"
dotnet user-secrets set "OptimizelyCmp:ClientSecret" "<your-client-secret>"

For CI/CD or hosted environments, use environment variables:

export OptimizelyCmp__ClientId="your-client-id"
export OptimizelyCmp__ClientSecret="your-client-secret"

Usage Example

using ImportAssetToOptiDam.Configuration;
using ImportAssetToOptiDam.Services.Authentication;
using ImportAssetToOptiDam.Services.Dam;
using ImportAssetToOptiDam.Services.Excel;
using ImportAssetToOptiDam.Services.Import;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Serilog;

Log.Logger = new LoggerConfiguration()
    .MinimumLevel.Information()
    .WriteTo.Console()
    .CreateBootstrapLogger();

var builder = Host.CreateApplicationBuilder(args);

builder.Configuration
    .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
    .AddEnvironmentVariables()
    .AddUserSecrets<Program>(optional: true);

builder.Services.AddSerilog();

builder.Services
    .AddOptions<OptimizelyCmpOptions>()
    .Bind(builder.Configuration.GetSection("OptimizelyCmp"))
    .ValidateOnStart();

builder.Services.AddSingleton<ITokenProvider, CachingTokenProvider>();
builder.Services.AddSingleton<IAssetImportReader, OpenXmlAssetImportReader>();
builder.Services.AddSingleton<IUploadReportWriter, XlsxUploadReportWriter>();
builder.Services.AddSingleton<AssetImporter>();

builder.Services.AddHostedService<ImportHostedService>();

await builder.Build().RunAsync();

Sample appsettings.json

{
  "Serilog": {
    "MinimumLevel": {
      "Default": "Information"
    }
  },
  "OptimizelyCmp": {
    "BaseUrl": "https://api.cmp.optimizely.com",
    "TokenUrl": "https://accounts.cmp.optimizely.com/o/oauth2/v1/token",
    "ApiVersion": "v3",
    "TokenRefreshSkewSeconds": 60,
    "FieldsPageSize": 100,
    "ClientId": "REPLACE_WITH_CLIENT_ID",
    "ClientSecret": "REPLACE_WITH_CLIENT_SECRET"
  },
  "Import": {
    "ImportFileName": "ImportAssetToOptiDam.xlsx",
    "ImportFolder": "ExcelSheet",
    "ImagesFolder": "Images",
    "SheetIndex": 0,
    "MaxDegreeOfParallelism": 1,
    "OutputFolder": "Output",
    "OutputFileName": "UploadReport-{date:yyyyMMdd}.xlsx"
  }
}

Excel Template

The import workbook is located at ExcelSheet/ImportAssetToOptiDam.xlsx.

The first worksheet is read by default. The first row must contain headers. Recognized headers are case-insensitive and can include spaces:

Header Purpose
Source Folder Path Optional source reference path.
OldFileName File name under the configured Images folder. Required.
NewFileName Title to apply to the DAM asset.
DAMFolderGuid DAM folder GUID. Used before DAM Folder Path when populated.
DAM Folder Path DAM folder path, for example Assets/TestFolderForDAMAutomation/VWTest.
Description Asset description.
AltText Image alt text.
Tags Comma-separated tags, for example hero,web,banner.

Any additional header is treated as a custom DAM field. If an active DAM field with the same name exists, the cell value is applied to that field. For choice fields, provide comma-separated choice names. Use ALL to select every choice.

Running

dotnet run --project ImportAssetToOptiDam

The app reads:

  • ExcelSheet/ImportAssetToOptiDam.xlsx
  • files from the configured Images folder
  • CMP credentials from configuration, user secrets, or environment variables

Output

After execution, the tool generates an Excel report in the configured Output folder.

The report contains:

  • New file name.
  • Public DAM URL.
  • Private DAM URL, when applicable.

Important Note

This tool is currently beta.

  • It is not production hardened.
  • Test in lower environments such as DEV or UAT before production use.
  • Keep CMP credentials out of source control and rotate any secret that has already been committed.
Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.1 107 4/28/2026
1.0.0 97 4/27/2026