AEM to Contentful Migration: A Step-by-Step Guide with Code Examples
Migrating content from Adobe Experience Manager (AEM) to Contentful involves several technical processes, including exporting data from AEM, restructuring it into a format that fits Contentful, and using APIs to import it into the new system. Since both AEM and Contentful work differently, understanding their API workflows and how to handle data transformation is crucial for a successful migration.
Below is a detailed walkthrough of how to migrate content from AEM to Contentful, including code examples for each stage of the process.
1. Extracting Content from AEM
The first step in the migration is extracting the content from AEM. AEM provides various APIs to access the content stored in its repository, including the Replicator API for exporting page data and the DAM API for handling digital assets.
Here’s an example of how you might use the Replicator API to export content from AEM:
// Example: Exporting AEM Content Using Replicator API (Java)
import org.apache.sling.api.servlets.SlingSafeMethodsServlet;
import javax.servlet.Servlet;
import org.osgi.service.component.annotations.Component;@Component(service = Servlet.class,
property = {
"sling.servlet.methods=GET",
"sling.servlet.paths=/bin/exportContent"
})
public class AEMContentExporterServlet extends SlingSafeMethodsServlet { @Override
protected void doGet(SlingHttpServletRequest request, SlingHttpServletResponse response) throws ServletException, IOException {
String path = request.getParameter("path");
if (path == null) {
response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
response.getWriter().write("Path parameter is required.");
return;
}
// Export content from AEM (simulate with mock data)
String exportedContent = exportContentFromAEM(path); // Respond with the exported content as JSON
response.setContentType("application/json");
response.getWriter().write(exportedContent);
} private String exportContentFromAEM(String path) {
// Mocked AEM export logic
return "{ \"path\": \"" + path + "\", \"content\": \"sample content\" }";
}
}
2. Converting Data for Contentful
Contentful operates on a headless, API-driven structure where all content is organized as entries, assets, and content types. After exporting content from AEM, you need to reformat it into a structure compatible with Contentful’s API.
Here’s how you might transform AEM data into the format required by Contentful:
// Example: Transforming AEM Data to Contentful Format
function transformToContentfulData(aemData) {
const contentfulEntry = {
fields: {
title: {
'en-US': aemData.content.title
},
body: {
'en-US': aemData.content.body
},
seo: {
'en-US': {
description: aemData.content.seoDescription,
keywords: aemData.content.seoKeywords
}
}
}
};return contentfulEntry;
}// Example AEM data
const aemDataSample = {
content: {
title: "Sample AEM Page Title",
body: "Content of the AEM page.",
seoDescription: "SEO content for the page.",
seoKeywords: "AEM, migration, SEO"
}
};// Transform into Contentful format
const contentfulData = transformToContentfulData(aemDataSample);
console.log(contentfulData);
3. Importing Data into Contentful
After transforming the data, you can use the Contentful Management API to import the content into Contentful. The Contentful SDK simplifies this process.
To start, install the Contentful SDK:
npm install contentful-managementHere’s an example of how to upload data to Contentful using the SDK:
const contentful = require('contentful-management');// Initialize the client with your access token
const client = contentful.createClient({
accessToken: 'your_management_api_key'
});async function createContentfulEntry(data) {
try {
// Access your Contentful space and environment
const space = await client.getSpace('your_space_id');
const environment = await space.getEnvironment('master'); // Replace 'master' if you use another environment // Create a new entry in Contentful
const entry = await environment.createEntry('page', {
fields: data.fields
}); console.log(`Entry created with ID: ${entry.sys.id}`);
} catch (error) {
console.error('Error creating entry:', error);
}
}// Import the transformed content into Contentful
createContentfulEntry(contentfulData);
4. Migrating Media (Assets)
When migrating media such as images, videos, or PDFs, you need to upload the assets separately to Contentful using the Asset API.
Get Phani Raj Kumar Bollipalli’s stories in your inbox
Join Medium for free to get updates from this writer.
Here’s an example of uploading an image:
async function uploadAsset(filePath) {
try {
// Get the space and environment
const space = await client.getSpace('your_space_id');
const environment = await space.getEnvironment('master');// Upload an asset
const asset = await environment.createAssetFromFiles({
fields: {
title: {
'en-US': 'Uploaded Image'
},
file: {
'en-US': {
contentType: 'image/jpeg',
fileName: 'image.jpg',
file: fs.createReadStream(filePath)
}
}
}
}); console.log(`Asset created with ID: ${asset.sys.id}`);
} catch (error) {
console.error('Error uploading asset:', error);
}
}// Example: Upload an image
uploadAsset('/path/to/image.jpg');
5. Managing Relationships Between Entries
If your AEM content contains references to other pages or resources, you will need to define these relationships in Contentful as references. Here’s an example of how to link entries in Contentful:
async function createLinkedEntry(formattedData, linkedEntryId) {
try {
// Access the space and environment
const space = await client.getSpace('your_space_id');
const environment = await space.getEnvironment('master');// Create a new entry with a linked reference
const entry = await environment.createEntry('page', {
fields: {
title: {
'en-US': formattedData.fields.title['en-US']
},
relatedPage: {
'en-US': {
sys: {
type: 'Link',
linkType: 'Entry',
id: linkedEntryId
}
}
}
}
}); console.log(`Entry created with linked reference: ${entry.sys.id}`);
} catch (error) {
console.error('Error creating linked entry:', error);
}
}// Example: Link a page entry to another
createLinkedEntry(contentfulData, 'linked_entry_id');
6. Verifying the Migration
Once you’ve migrated all the content, you’ll want to verify that everything is correctly imported into Contentful. This includes checking that:
- Entries have been created with the correct fields.
- Assets are correctly linked to their respective entries.
- References between entries are functional.
Conclusion
Migrating content from AEM to Contentful requires extracting data from AEM, transforming it into a compatible format, and using Contentful’s APIs to import the content. This process involves:
- Exporting content from AEM using APIs.
- Converting data to fit Contentful’s structure.
- Uploading content and media via Contentful’s Management API.
- Creating relationships between entries when necessary.
By following this guide, you can ensure a smooth migration, leveraging the power of Contentful’s headless CMS while preserving your content structure from AEM.
This rephrased version presents the same steps but with unique phrasing to provide a fresh perspective on the migration process.





