I'm migrating products from an existing non-Drupal, sql-based site into a new Drupal 8 Commerce site. But products belong to stores. So, I need to set up a store before I can create my products. Now, I could have just used the admin UI to set up a store. But then I need to hard-code the store ID into my products migration config, which I'd like to avoid. Instead, I used the embedded_data source plugin. The embedded data source plugin allows you to enter source data directly into a migration configuration yaml file. And it works brilliantly for creating just a few content entities. (Or just one content entity, the default store, in this case.)

The id of the store migration config is set to commerce_store (but can be set to anything you want):

id: commerce_store

The migration "source" config is defined as follows:

source:
  plugin: embedded_data
  data_rows:
    -
      id: default_store
      type: online
      name: 'Worthington Biochemical'
      mail: custservice@example-domain.com
      default_currency: USD
      country_code: US
      administrative_area: NJ
      locality: Lakewood
      postal_code: '08701'
      address_line1: '730 Vassar Ave'
  ids:
    id:
      type: string

The two components of the embedded_data plugin are the data_rows and ids. Use - for each data row, i.e., entity that should be created. In this case, there's only one store and only one data row. To create a second store, copy everything from - to address_line1: '730 Vassar Ave' and paste it right below address_line1: '730 Vassar Ave'. Then change all the values especially the id value, since that needs to be unique for each data row/entity.

Note that the default currency is set to USD. If that's not the currency for your store, you'll need to add the one(s) you need.

id: default_store can be any combination of a key/value pair. default_store will be used in the products migration to reference this commerce store data (see below). id gets referenced in the ids: section of the source plugin config. This is an id of type string. Alternatively, the id type could be set as integer.

The rest of the key values in the data_rows section of the source plugin can also be given any names that make sense for the data. Those key values are how the data will be referenced by the process plugin config.

So, here's the migration config "process" section:

process:
  type: type
  name: name
  mail: mail
  default_currency: default_currency
  address/country_code: country_code
  address/administrative_area: administrative_area
  address/locality: locality
  address/postal_code: postal_code
  address/address_line1: address_line1

Here, the key values do matter. They correspond to the field names of the commerce_store entity. There are several other commerce_store fields that could also be included:

  • langcode
  • uid
  • address/langcode
  • address/dependent_locality
  • address/sorting_code
  • address/address_line2
  • address/organization
  • address/given_name
  • address/additional_name
  • address/family_name
  • default_langcode
  • prices_include_tax

The values for each of the key/value pairs in the process section of the migration config correspond to the keys provided by the embedded data source plugin.

Lastly, the destination plugin is set to the commerce store entity:

destination:
  plugin: 'entity:commerce_store'

Here's the complete source code for my commerce store migration: migrate_plus.migration.commerce_store.yml

After running the commerce store migration, there's one little "gotcha" to be aware of. You need to edit-and-save the store using the admin ui (Commerce > Configuration > Store > Stores). This sets the store as the "default store" (even if you've only got a single store.) If you don't, other things may mysteriously not work later on...