App Owned Metaobject Access in Liquid

Hi there!

I am working on building an app which creates custom metaobject definition and objects using the Admin API / GraphQL. I cannot figure out how to access it from my Theme App Extension / Embed? From the documentation (The Documentation), it seemed like I should be able to add the storefront access as seen below in the definition.

I verified via my API that I can create/edit/retrieve objects, and that they are set to published status ‘ACTIVE’.

The definition is below:

{
  name: "xxxxxxxxxx",
  type: "$app:xxxxxxxxxx",
  description: "xxxxxxxxxx",
  fieldDefinitions: [
    {
      description: "xxxxxxxxxx",
      key: "xxxxxxxxxx_json",
      name: "xxxxxxxxxx JSON",
      required: true,
      type: "json",
      validations: [],
    },
  ],
  access: {
    admin: "MERCHANT_READ",
    storefront: "PUBLIC_READ",
  },
  capabilities: {
    publishable: {
      enabled: true,
    },
    translatable: {
      enabled: false,
    },
  },
}

I feel like I have tried every combination of liquid similar to the following:

{{ shop.metaobjects['type'].values }}
{{ app.metaobjects['type'].values }}
{{ shop.metaobjects['$app:type'].values }}
{{ app.metaobjects['$app:type'].values }}
{{ app.metafields.values }}

EDIT: Adding link to another developer’s post explaining the exact issue wwe are seeing: How to access app owned meta object in theme app extensions’s liquid file?
https://community.shopify.com/c/technical-q-a/how-to-access-app-owned-meta-object-in-theme-app-extensions-s/m-p/2166426/thread-id/134476

2 Likes

Hi RiptideApps,

Have you tried this format to access an app’s metafields in Liquid:

{{ app.metafields.namespace.key }}

1 Like

So, based on this metaobject data (retrieved from GraphQL API), I tried the following combinations…

{
  capabilities: {
    publishable: {
      status: "ACTIVE",
    },
  },
  definition: {
    id: "gid://shopify/MetaobjectDefinition/XXXXXXX",
    name: "XXXXXXXXXXX",
    type: "app--XXXXXXXX--XXXXXXX_XXXX",
    access: {
      admin: "MERCHANT_READ",
      storefront: "PUBLIC_READ",
    },
  },
  fields: [
    {
      value: "[{XXXX_JSON_DATA_XXXXX}]",
      key: "XXXX__KEY_NAME__XXXX_json",
    },
  ],
  displayName: "App  XXXXXXXXXX XXXXX #MSXXXXXXXX",
  handle: "app--XXXXXXXXX--XXXX-XXXXX-XXXXXXXX",
  id: "gid://shopify/Metaobject/XXXXXXXXX",
  type: "app--XXXXXXXXXXX--XXXX__METAOBJ_DEF_TYPE__XXXX",
  updatedAt: "2023-09-17T04:49:02Z",
}
"{{ app.metafields.XXXX__METAOBJ_DEF_TYPE__XXXX.XXXX__KEY_NAME__XXXX.value | json }}",
    "{{ app.metafields.XXXX__METAOBJ_DEF_TYPE__XXXX.XXXX__KEY_NAME__XXXX}}",
    "{{ app.metafields.XXXX__METAOBJ_DEF_TYPE__XXXX.XXXX__KEY_NAME__XXXX.value }}",
    "{{ app.metafields.XXXX__METAOBJ_DEF_TYPE__XXXX.XXXX__KEY_NAME__XXXX | json }}"

/** 
** Note: I am NOT including the "$app:" prefix
**  or the "app-123456" prefix to any of the types above
**/
1 Like

did you find a solution for this problem? I’m in the same situation and can’t find a solution

I ended up using

{{ shop.metafields.app--APP_ID--properties.KEY }}

APP_ID is constant so there shouldn’t be any problems. But yes, it’s ugly.

We manage multiple custom apps and needed a more automated solution. We haven’t found a simpler solution -there might be one-, so this is what we did:

  1. Resolve your owned metafield namespace by querying the “currentAppInstallation” with the admin API:
query currentAppInstallation {
  currentAppInstallation {
    id  # This will be used to set a metafield in a later mutation
    app {
      id  # This is your app ID, that is part of the resolved namespace
    }
  }
}

then, the namespace will be **app--{currentAppInstallation.app.id}--{your-namespace}**.

  1. Store it in a metafield in the currentAppInstallation:
mutation CreateAppDataMetafield($metafieldsSetInput: [MetafieldsSetInput!]!) {
  metafieldsSet(metafields: $metafieldsSetInput) {
    metafields {
      id
      namespace
      key
      value
    }
    userErrors {
      field
      message
    }
  }
}

variables:

{
    "metafieldsSetInput": [
        {
            "namespace": "{your-namespace}",
            "key": "meta_namespace",
            "type": "single_line_text_field",
            "value": "app--{**currentAppInstallation.app.id**}--{your-namespace},
            "ownerId": {**currentAppInstallation.id**},
        }
    ]
}
  1. Finally, you can access from the liquid template your own metafields on other objects like this:
{% assign resolved_namespace = app.metafields.{your-namespace}.meta_namespace %}
{% assign your_metafield_value = block.settings.product.metafields[resolved_namespace].{your-metafield-key}.value %}

Hope it helps!

2 Likes