Core Functionalities
Metaobject API

Working with MetaObjects in ShipReady

What are MetaObjects in Shopify?

MetaObjects in Shopify are customizable data structures that allow you to create and manage complex, structured data that doesn't fit into Shopify's standard data models. They are particularly useful for:

  • Creating custom content types (e.g., recipes, team members, FAQ entries)
  • Organizing related pieces of information
  • Building flexible, app-specific data structures
  • Storing app data that needs to be accessed and managed by merchants

MetaObjects consist of a definition (which defines the structure) and instances (which contain the actual data).

Using the MetaObject Class in ShipReady

ShipReady provides a powerful MetaObject class to simplify working with Shopify's metaobjects. Here's how to use each method:

Initializing the MetaObject Class

First, import and initialize the MetaObject class:

import { MetaObject } from "../entities/metaobject.js";
 
const metaobject = new MetaObject(admin);

Defining a MetaObject

Use the define method to create a new MetaObject definition. The method now includes error handling for cases where the definition already exists:

try {
  const definition = await metaobject.define({
    name: "Recipe",
    type: "recipe",
    access: {
      admin: "MERCHANT_READ_WRITE",
      storefront: "PUBLIC_READ"
    },
    fieldDefinitions: [
      { key: "title", name: "Title", type: "single_line_text_field" },
      { key: "ingredients", name: "Ingredients", type: "multi_line_text_field" },
      { key: "instructions", name: "Instructions", type: "multi_line_text_field" },
      { key: "prep_time", name: "Preparation Time", type: "number_integer" }
    ]
  });
 
  console.log(definition);
  // Output: { metaobjectDefinition: { name: "Recipe", type: "recipe", fieldDefinitions: [...] }, userErrors: [] }
} catch (error) {
  if (error.message.includes("Type has already been taken")) {
    console.log("MetaObject definition already exists");
  } else {
    console.error("Error defining MetaObject:", error);
  }
}

Getting a MetaObject Definition

Retrieve an existing MetaObject definition:

try {
  const recipeDefinition = await metaobject.getDefinition({ type: "recipe" });
 
  console.log(recipeDefinition);
  // Output: { id: "gid://shopify/MetaobjectDefinition/1234", name: "Recipe", type: "recipe", fieldDefinitions: [...] }
} catch (error) {
  console.error("Error getting MetaObject definition:", error);
}

Deleting a MetaObject Definition

Remove a MetaObject definition:

try {
  const deletedDefinition = await metaobject.deleteDefinition({ type: "recipe" });
 
  console.log(deletedDefinition);
  // Output: { deletedId: "gid://shopify/MetaobjectDefinition/1234", userErrors: [] }
} catch (error) {
  console.error("Error deleting MetaObject definition:", error);
}

Creating a MetaObject Instance

Create a new instance of a MetaObject:

try {
  const recipeInstance = await metaobject.create(
    { 
      type: "recipe",
      fieldDefinitions: [
        { key: "title" },
        { key: "ingredients" },
        { key: "instructions" },
        { key: "prep_time" }
      ]
    },
    {
      title: "Chocolate Chip Cookies",
      ingredients: "Flour, Sugar, Butter, Chocolate Chips",
      instructions: "Mix ingredients, bake at 350°F for 10 minutes",
      prep_time: 15
    }
  );
 
  console.log(recipeInstance);
  // Output: { id: "gid://shopify/Metaobject/5678", handle: "chocolate-chip-cookies", type: "recipe" }
} catch (error) {
  console.error("Error creating MetaObject instance:", error);
}

Finding a MetaObject Instance

Retrieve a specific MetaObject instance:

try {
  const foundRecipe = await metaobject.find(
    { 
      fieldDefinitions: [
        { key: "title" },
        { key: "ingredients" },
        { key: "instructions" },
        { key: "prep_time" }
      ]
    },
    "gid://shopify/Metaobject/5678"
  );
 
  console.log(foundRecipe);
  // Output: { id: "gid://shopify/Metaobject/5678", handle: "chocolate-chip-cookies", type: "recipe", title: "Chocolate Chip Cookies", ... }
} catch (error) {
  console.error("Error finding MetaObject instance:", error);
}

Updating a MetaObject Instance

Update an existing MetaObject instance:

try {
  const updatedRecipe = await metaobject.update(
    { 
      fieldDefinitions: [
        { key: "title" },
        { key: "ingredients" },
        { key: "instructions" },
        { key: "prep_time" }
      ]
    },
    "gid://shopify/Metaobject/5678",
    {
      prep_time: 20
    }
  );
 
  console.log(updatedRecipe);
  // Output: { id: "gid://shopify/Metaobject/5678", handle: "chocolate-chip-cookies", type: "recipe" }
} catch (error) {
  console.error("Error updating MetaObject instance:", error);
}

Listing MetaObject Instances

Retrieve a list of MetaObject instances with pagination support:

async function listRecipes(limit = 10) {
  let allRecipes = [];
  let hasNextPage = true;
  let cursor = null;
 
  while (hasNextPage) {
    try {
      const result = await metaobject.list(
        { 
          type: "recipe",
          fieldDefinitions: [
            { key: "title" },
            { key: "ingredients" },
            { key: "instructions" },
            { key: "prep_time" }
          ]
        },
        limit,
        cursor
      );
 
      allRecipes = allRecipes.concat(result.nodes);
      hasNextPage = result.pageInfo.hasNextPage;
      cursor = result.pageInfo.endCursor;
    } catch (error) {
      console.error("Error listing MetaObject instances:", error);
      break;
    }
  }
 
  console.log(allRecipes);
  return allRecipes;
}
 
listRecipes();

Deleting a MetaObject Instance

Remove a MetaObject instance:

try {
  const deletedId = await metaobject.delete("gid://shopify/Metaobject/5678");
 
  console.log(deletedId);
  // Output: "gid://shopify/Metaobject/5678"
} catch (error) {
  console.error("Error deleting MetaObject instance:", error);
}

Best Practices

  1. Plan your MetaObject structure carefully before defining it.
  2. Use meaningful names and keys for your MetaObject fields.
  3. Consider access levels (admin and storefront) when defining MetaObjects.
  4. Implement proper error handling for all MetaObject operations.
  5. Use pagination when listing MetaObjects to handle large datasets efficiently.
  6. Cache MetaObject definitions when appropriate to reduce API calls.
  7. Use MetaObjects to organize related data that doesn't fit into Shopify's standard models.

For more information on MetaObjects in Shopify, refer to the official Shopify documentation (opens in a new tab).

If you encounter any issues or have questions about using MetaObjects in ShipReady, please check our Troubleshooting page or contact our support team.