Skip to main content
OZAN ALTINBAS
Architecture

SiteGenesis to SFRA Migration: A Technical Guide for SFCC Teams

By 13 min read

SiteGenesis is the storefront framework B2C Commerce sites ran on before Salesforce launched the Storefront Reference Architecture (SFRA) as its successor in 2018. Moving from one to the other is not an upgrade: the two share the platform, the data and the ISML template language, but almost none of the storefront code.

This guide covers Salesforce's actual position on SiteGenesis support, the three realistic routes, the code inventory, how each SiteGenesis concept maps to SFRA, and how to protect SEO and cut over in a way you can reverse. For the platform itself, start with the SFCC guide.


Is SiteGenesis end of life?

No. Salesforce has announced no end-of-life date for SiteGenesis or for pipelines:

  • A Salesforce knowledge article published in December 2025 states there is no plan to deprecate B2C Commerce pipelines and require JavaScript controllers only.
  • The SFRA FAQ, written when SFRA launched, says SiteGenesis merchants are not required to move and that SiteGenesis keeps receiving high-priority bug and security fixes. That launch-era position has not been withdrawn, but it carries no date.

What has changed is everything around SiteGenesis:

  • Salesforce's storefront chooser lists Storefront Next (recommended), SFRA, a hybrid of the two and a custom build. SiteGenesis is not an option.
  • Salesforce Payments ships as an SFRA plug-in cartridge; on SiteGenesis the documented workaround is to add it to the cartridge path as a library, which Salesforce notes doesn't work in all instances.
  • Legacy jobs, which run pipelines, are deprecated and listed under Administration > Operations > Jobs (Deprecated).

The real question is what standing still costs.


SiteGenesis vs SFRA: what actually differs

"SiteGenesis" covers two code bases. The original, which Salesforce's documentation calls SiteGenesis Pipeline Processor (SGPP), handles requests in pipelines: XML flows edited in UX Studio, an Eclipse plug-in, whose nodes call pipelets and scripts and render templates. The later SiteGenesis JavaScript Controllers (SGJC) edition uses CommonJS controllers in app_storefront_controllers, layered on app_storefront_core.

AreaSiteGenesisSFRA
Request handlingPipelines (SGPP) or JavaScript controllers (SGJC)Controllers whose routes are registered through the server module
Base codeapp_storefront_core, plus app_storefront_controllers in SGJCapp_storefront_base, plus the modules cartridge that holds server
CustomisationOverride cartridge in front of the baseOverlay cartridges using server.append, prepend or replace
Template dataTypically Script API objects in pdictPlain JSON view models from cartridge/models
Request and session logicOnRequest and OnSession pipelines or controllersdw.system.request.onRequest and onSession hooks
Front endSiteGenesis markup, styles and scriptsBootstrap 4 and jQuery, built with sgmf-scripts
Add-on featuresPlug-in cartridges are hard to overlayBase, plug-in, LINK and custom layers on one path

Two platform behaviours matter during a migration (SFRA features and components):

  • B2C Commerce treats SGJC and SFRA controllers as equals and runs the first controller with the requested name on the cartridge path. If none matches, it runs the first matching pipeline, so a SiteGenesis cartridge left on an SFRA site's path keeps its old endpoints reachable.
  • SFRA's base cartridge and server module are guaranteed backward compatible between point releases only while you leave them unedited. Customise in your own app_custom_* overlays; the cartridge development guide covers the pattern.

Choosing a migration route

Route 1: rebuild the storefront on SFRA

Start from app_storefront_base, rebuild the design in overlay cartridges and port SiteGenesis features one at a time. The SFRA FAQ is explicit that existing data, merchant rules and back-end integrations are unaffected; only the storefront code base changes.

Route 2: migrate one site at a time

The FAQ confirms SiteGenesis and SFRA can run on different brands or regions at the same time, at the cost of extra operational and code-management complexity. Cartridge paths are set per site and a code version is a folder of cartridges, so one code version can carry both stacks. Migrate the smallest site first.

Salesforce does not describe mixing SiteGenesis and SFRA on one site's cartridge path. Both ship a Cart controller and the first match wins, so within a single site, plan one storefront cut-over.

Route 3: skip SFRA and go headless

Salesforce's Storefront Next Migration Tool is an AI-assisted CLI that analyses a live SiteGenesis, SFRA or PWA Kit storefront and generates a Storefront Next scaffold route by route. It is a developer preview, it needs read-only OCAPI and WebDAV access for SiteGenesis, and it doesn't evaluate pipelines: pipeline and custom server-side work stay manual. Salesforce documents Hybrid Auth for running Storefront Next beside a live SFRA or SiteGenesis site. The architectural trade-offs are in SFRA vs PWA Kit.

SituationRoute
One site, redesign due, Script API and ISML teamRebuild on SFRA
Several sites on one realmSFRA, site by site, smallest first
React team with a long-term headless planStorefront Next, with pipeline logic budgeted as manual work
Heavy pipeline logic, many partner cartridges with UISFRA first; headless later if still wanted

Step 1: inventory the SiteGenesis code base

Estimate from an inventory, not from a page count. Per site, record:

ItemWhat to recordWhy it matters
Cartridge pathEvery cartridge, in order (Administration > Sites > Manage Sites)Separates your code, SiteGenesis base code and partner code
PipelinesStart nodes, the pipelets they call, interaction continue nodesEach becomes a route, a script or a job step
SGJC controllersEvery public Controller-FunctionBecomes an SFRA route or a base-route extension
Scripts.ds and .js modules, and their pipelet callsScript API code ports; pipelet calls need replacing
ISML templatesPages, includes, slot rendering templatesRewritten for SFRA's models and layouts
Form definitionsEach XML file, per locale folderFormat unchanged; the plumbing changes
JobsLegacy pipeline jobs and job-framework stepsLegacy jobs move to the job framework
HooksEvery hooks.json entryMost port; diff them against SFRA's own
IntegrationsVendor, version, SFRA availabilityOften the critical path
Inbound endpoint namesNames used in static mappings, URL rules, content assets, emails and partner callbacksEach must still resolve after cut-over

The last row is the one most often missed: search the content library export, email templates and partner settings for endpoint names, not just the code. For LINK cartridges, the FAQ told teams at SFRA's launch to check for SFRA-certified versions. That still applies: confirm each vendor publishes an SFRA cartridge, and treat the switch as a new integration with its own install guide and regression tests.


Step 2: map SiteGenesis concepts to SFRA

Pipelines and SGJC controllers become SFRA routes

There is no converter. Each pipeline start node or SGJC public function becomes a route registered with server.get or server.post in cartridge/controllers. Middleware such as server.middleware.https takes over the checks a pipeline made first, models replace the pipeline dictionary, and res.render or res.json replaces template rendering.

Interaction continue nodes need special care. An interaction continue node renders a template, typically a form, and the same pipeline continues on the next request, so one flow spans several requests. Split each into a GET route that renders the form and a POST route that handles it.

The Script API's dw.system.Pipeline.execute() was added to ease migration to controllers, but it only runs pipelines without user interaction. Salesforce's controller guidelines strongly discourage calling pipelets from controllers and call calling pipelines "highly discouraged" outside existing LINK cartridges. Treat it as a short-lived bridge at most, and replace pipelet calls with Script API methods wherever an equivalent exists.

Forms: same definitions, new plumbing

SFRA reads the same XML form definitions. Salesforce's forms documentation still uses SiteGenesis's contactus.xml as an example, and locale variants still live in forms/default and per-locale folders. What changes: server.forms.getForm() builds a JSON form object, templates use standard HTML forms, submitted values arrive in req.form, and persistence goes in a route:BeforeComplete handler. SFRA ships no dynamic, multi-part, embedded or nested forms.

// app_custom_mybrand/cartridge/controllers/Feedback.js
'use strict';

var server = require('server');
var URLUtils = require('dw/web/URLUtils');
var csrfProtection = require('*/cartridge/scripts/middleware/csrf');

// GET: replaces the pipeline branch that rendered the empty form
server.get('Show', server.middleware.https, csrfProtection.generateToken, function (req, res, next) {
    var feedbackForm = server.forms.getForm('feedback'); // forms/default/feedback.xml
    feedbackForm.clear();

    res.render('feedback/form', {
        feedbackForm: feedbackForm,
        actionUrl: URLUtils.url('Feedback-Submit').toString()
    });
    next();
});

// POST: handles the submit the interaction continue node used to continue from
server.post('Submit', server.middleware.https, csrfProtection.validateAjaxRequest, function (req, res, next) {
    var feedbackForm = server.forms.getForm('feedback');

    if (!feedbackForm.valid) {
        res.json({ success: false });
        return next();
    }

    this.on('route:BeforeComplete', function () {
        // Persist here (custom object, service call) inside a Transaction
    });

    res.json({ success: true });
    return next();
});

module.exports = server.exports();

OnRequest and OnSession become hooks

SFRA doesn't use the OnRequest and OnSession handlers SiteGenesis implemented as pipelines or controllers; Salesforce says to implement them as hooks, which have no access to req and res. Register the dw.system.RequestHooks extension points in the hooks file that the cartridge's package.json points to ("hooks": "./hooks.json"). Script paths are relative to that file:

{
  "hooks": [
    { "name": "dw.system.request.onSession", "script": "./cartridge/scripts/hooks/request/onSession.js" },
    { "name": "dw.system.request.onRequest", "script": "./cartridge/scripts/hooks/request/onRequest.js" }
  ]
}

Each script exports onSession or onRequest and returns a dw.system.Status; without req and res, it works with the global request and session objects.

Templates, client-side code and content slots

ISML is the same language, but templates are rewritten: SFRA templates read JSON models, sit in SFRA's Bootstrap 4 layouts and register CSS and JavaScript through the assets module (assets.addCss, assets.addJs). Client-side code is SFRA's jQuery-based scripts built with sgmf-scripts; SiteGenesis client scripts don't carry over. Resource bundles in templates/resources carry over as files, but must be merged into SFRA's keys.

Business Manager reads slot IDs and templates from the templates on the cartridge path (content slot processing). Slot configurations survive as data, but every <isslot> ID and rendering template they reference must exist in the new templates, or that content stops appearing.

Jobs move to the job framework

Legacy pipeline jobs are deprecated whichever storefront you choose. A steptypes.json in the cartridge root can declare a pipeline-step that runs an existing process pipeline as an interim measure; chunk-oriented steps can't use pipelines (custom job steps). The end state is a CommonJS script-module-step:

{
  "step-types": {
    "pipeline-step": [
      {
        "@type-id": "custom.LegacyStockExport",
        "@supports-parallel-execution": "false",
        "@supports-site-context": "true",
        "@supports-organization-context": "false",
        "description": "Interim step: runs the SiteGenesis process pipeline unchanged",
        "pipeline": "StockExport-Start",
        "status-codes": {
          "status": [
            { "@code": "ERROR", "description": "The step failed." }
          ]
        }
      }
    ],
    "script-module-step": [
      {
        "@type-id": "custom.StockExport",
        "@supports-parallel-execution": "false",
        "@supports-site-context": "true",
        "@supports-organization-context": "false",
        "description": "Replacement step written as a CommonJS module",
        "module": "int_stock_export/cartridge/scripts/steps/stockExport.js",
        "function": "execute",
        "transactional": "false",
        "timeout-in-seconds": "900",
        "status-codes": {
          "status": [
            { "@code": "ERROR", "description": "The step failed." },
            { "@code": "OK", "description": "The step finished successfully." }
          ]
        }
      }
    ]
  }
}

Each cartridge holds only one steptypes.json or steptypes.xml; job parameters and the other options follow Salesforce's steptypes.json example. A pipeline step needs the pipeline's cartridge on the cartridge path, which is one more reason to retire these steps quickly.

Hooks and integrations

Hooks in hooks.json are platform extension points, not SiteGenesis code, so most port with little change. The exception is anything SFRA already implements. SFRA's base cartridge ships its own basket calculation hook script, scripts/hooks/cart/calculate.js, which its JSDoc describes as letting the storefront and OCAPI share one cart calculation, so diff a customised dw.order.calculate hook against it instead of copying it over. Service configurations in Business Manager stay; only the code that calls them moves.


What carries over unchanged

Per the SFRA FAQ, adopting SFRA leaves existing data, merchant rules and back-end integrations unaffected. In practice:

Carries over as isNeeds review
Catalogues, price books and inventoryContent assets using SiteGenesis CSS classes or linking to SiteGenesis endpoints
Customers and order historySlot configurations: their slot IDs and rendering templates must exist in SFRA
Promotions, campaigns and customer groupsCustom attributes and site preferences that only SiteGenesis code reads
URL rules, static mappings and redirects, as configurationRule and mapping targets that name SiteGenesis-only endpoints
Service configurationsLegacy pipeline jobs, and jobs whose steps come from SiteGenesis cartridges

SFRA keeps Link-Category, Link-Page and Link-Product for source-code redirects, plus Link-CategoryProduct to support legacy content assets that link to specific pipelines (SFRA JSDoc). For custom endpoints, the cheapest fix is often to give the SFRA controller and route the SiteGenesis name, so every rule, mapping and link that uses it keeps working.


SEO continuity

The storefront changes; the URLs should not. Most of the work is configuration that already exists:

  • URL rules stay. Category, product and content URLs come from the site's URL rules (Merchant Tools > Site > SEO & Discoverability > URL Rules), provided SFRA templates build links with URLUtils to the standard routes. Crawl both storefronts and diff the URL sets anyway.
  • Pipeline URLs need checking. URL rules also cover pipeline URLs. The URL Archive redirects outdated mappings to current ones, and its cleanup search finds mappings that reference no valid category, folder or pipeline. Run it after cut-over.
  • Static mappings target endpoints by name. Every static mapping target must exist in SFRA. Mappings require a hostname alias, replicate from staging to production, and are limited to 2 MB in Business Manager (larger sets go through site import).
  • Diff the rendered head. For the top URLs in Search Console, compare <title>, meta description, canonical, hreflang and structured data between the two renders. Anything SiteGenesis templates hard-coded is missing until you port it.
! legacy URL -> endpoint that exists in SFRA's app_storefront_base
/summer-sale p,,,Link-Category,,cgid,summer-sale
/about-us p,,,Link-Page,,cid,about-us

The Commerce Cloud SEO guide covers the platform settings, and the Commerce Cloud migration guide covers redirect mapping and Search Console monitoring.


Testing and cut-over

What to test

  • URL replay. Request every URL in the inventory (Search Console exports, static mappings, sitemaps, email links) against the SFRA staging site and assert the status code and final URL.
  • Checkout matrix. Every payment and shipping method, guest and registered, in every locale.
  • Jobs and integrations. Each job on staging with production-like data; each partner integration end to end.
  • Performance. SFRA sets the page cache per route with middleware: confirm cacheable pages are cached, and compare field data for revenue templates.

Cut-over on one code version

Code deployment gives you the building blocks. An instance runs one active code version; best practice is to upload to an inactive version on staging, test it, and replicate it to production. Activation clears cached items, and Rollback reactivates the previous version if it is still installed. Cartridges are assigned per site under Administration > Sites > Manage Sites.

An approach built on those facts (rehearse it on staging; it is not a Salesforce-prescribed procedure):

  1. Build one code version that contains both the SiteGenesis and the SFRA cartridges. Activating it changes nothing for shoppers while the site's cartridge path still lists SiteGenesis cartridges.
  2. Replicate the URL rules, static mappings and other configuration the SFRA storefront needs.
  3. At the agreed time, switch the site's cartridge path to the SFRA stack and invalidate the page cache.
  4. To roll back, switch the path back; no code deployment is needed.
  5. Once the site is stable, drop the SiteGenesis cartridges from later code versions so no forgotten pipeline stays reachable.

A phased plan

PhaseWorkExit criterion
0. DecideSFRA or headless; site order on multi-site realmsAgreed route and first site
1. InventoryThe step 1 table, per siteEvery endpoint, job, hook and integration has an owner and a target
2. FoundationSFRA base and modules, app_custom_* skeleton, SFRA partner cartridges, sgmf-scripts buildSFRA running on a sandbox with your data
3. PortRoutes, models, templates, forms, hooks, designFeature parity list closed
4. Jobs and integrationsLegacy jobs moved to the job framework; regression testsEvery job runs on staging
5. SEOURL rules, static mappings, head-tag diffURL replay passes
6. RehearseCut-over and rollback on stagingTimed runbook; rollback proven
7. LaunchCartridge-path switch, hypercareErrors, conversion and crawl stats steady
8. DecommissionSiteGenesis cartridges removed; URL Archive cleanedNo SiteGenesis code in the active version

Key takeaways

  • SiteGenesis has no announced end of life, and Salesforce has no plan to deprecate pipelines. The pressure is that new features such as Salesforce Payments target SFRA, and the storefront chooser omits SiteGenesis.
  • The migration is a storefront rewrite on unchanged data. Catalogues, customers, orders and Business Manager configuration stay; controllers, templates and client code are rebuilt.
  • Inventory endpoints, not pages. Every pipeline or controller name used by URL rules, static mappings, content or partners must resolve after cut-over.
  • Pipelines become GET and POST route pairs, OnRequest and OnSession become hooks, legacy jobs move to steptypes.json, and forms keep their XML definitions.
  • One code version holding both stacks turns cut-over and rollback into a cartridge-path change. If the long-term target is headless, evaluate Storefront Next first; its migration tool leaves pipeline logic as manual work.

For a migration assessment or an SFRA rebuild plan, see the SFCC consulting services or get in touch.

Further reading