【Shopify】GraphiQLでshopのmetafieldにmetaobjectを設定する

## metafieldをshopに設定したい。

管理画面／設定のカスタムデータからは「ショップ」にmetafieldを設定することができない...

じゃあどうやってshopのmetafieldを設定することができるのか?

## APIで設定する

リファレンスを読むと「APIからなら設定できるよ」的な記載がありました。
(2024年7月現在)

どうしようか考えた結果、「GraphiQL」からが手っ取り早いと判断しました。
(GraphiQLの導入は調べるとすぐ出てくるのでここでは割愛します)


## GraphiQLの権限について

GraphiQLのデータアクセスの権限は [こちら >](https://shopify-graphiql-app.shopifycloud.com/login) で変更しましょう。

とりあえず「metaobject_definitions」と「metaobjects」の「read」と「write」のチェックを追加してインストール(既にGraphiQL appをインストールしていたらもう一回インストール手順)。

※ インストールするShop URLはショップの公開URLではなく管理画面のURL


## shopにメタフィールドを設定する前に

今回は設定したいmetafieldのtypeがmetaobjectだったので、metaobjectの定義情報とエントリーは予め管理画面から作成しておきました。


## shopのメタフィールドを確認する

まずは自分が設定しようと考えているmetafield(ネームスペースとキー)が既にshopに存在しているかどうかを一応確認しておきます。

インストールした「Shopify GraphiQL App」で下記のqueryを実行します。

``` graphQL
{
    shop {
        metafield(namespace:"hoge",key:"fuga") {
            id
        }
    }
}
```

これでnullが返ってくれば安心です。もし値が帰ってきてしまったら、namespaceとkeyを再検討しましょう。

次にこの後必要になる諸情報を取得していきます。

## shopのidを調べる

``` graphQL
{
    shop {
        id
    }
}
```

idは「"gid://shopify/Shop/***********"」の様な形式になります。

## metaobjectの定義情報を調べる

metafieldのタイプにmetaobjectを設定する場合、そのmetaobjectの定義情報(というかid)が必要になるので事前に調べておきます。

以下のqueryを実行するとmetaobjectの定義情報が指定した件数分返ってきます。
(ただこれはもっと良い方法があると思います...)

``` graphQL
{
	metaobjectDefinitions(first:件数) {
        nodes {
          id
          name
          displayNameKey
        }
    }
}
```

戻り値の中で対象のmetaobjectのidが必要になります。

## metaobjectのエントリー情報を調べる

次に設定したいmetaobjectのエントリー情報を取得します。
このmetaobjectのエントリー情報は、自身で定義したmetafieldにデータを設定する際に必要となります。

``` graphQL
{
	metaobjects(type:"定義名",first:件数) {
    nodes {
      id
      displayName
    }
  }
}
```
queryで必要なmetaobjectの「定義名」は自身で予め作っておいたものになります。

(これも、もっと良い取得方法があると思います...)

## shopにmetafieldの定義を追加

それではいよいよshopにmetafieldを追加します。

metafieldの設定を新たに定義するので「mutation」を実行しますが、今回実行するmutationは [APIのリファレンス](https://shopify.dev/docs/api/admin-graphql/2024-01/mutations/metafieldDefinitionCreate) からコピーできるので有効活用します。

``` graphQL
mutation CreateMetafieldDefinition($definition: MetafieldDefinitionInput!) {
  metafieldDefinitionCreate(definition: $definition) {
    createdDefinition {
      id
      name
    }
    userErrors {
      field
      message
      code
    }
  }
}
```

次に設定したいmetafieldの「Variables(値)」の雛形もリファレンスの同じページからコピーしてしまいます。
ここで設定するmetafieldの「namespace」と「key」は先ほど存在検証をしたものを設定します。

``` javascript
{
  "definition": {
    "name": "任意のメタフィールド名",
    "namespace": "hoge",
    "key": "fuga",
    "description": "メタフィールドの説明文",
    "ownerType": "SHOP",
    "type": "metaobject_reference",
    "validations": {
      "name": "metaobject_definition_id",
      "value": "gid://shopify/MetaobjectDefinition/**********"
    }
  }
}

```

* ownerType : 「_SHOP_」(半角大文字)を設定することでshopが対象となります。
* type : 今回はmetafieldのタイプをmetaobjectにしたい場合は「_metaobject_reference_」にします。
* validations : コピーしてきた雛形に「varidations」を追加します。このvalidationsで設定したいmetaobjectを指定します。

## validationsとは

この「validations」とは何なのか。

ざっくり言ってしまえば、本当にそのまんまの意味で「type」で指定した「型」について、どんなデータを許可するかの設定になります。

``` javascript
"validations": {
    "name": "metaobject_definition_id",
    "value": "gid://shopify/MetaobjectDefinition/**********"
}
```

「name」は検証する対象を、「value」は許可する値を設定してあげます。

なので今回は「どのmetaobject」を許可してあげるのかを設定します。

* name : metaobjectの定義IDを検証させたいので「metaobject_definition_id」
* value : 許可するのはどの定義IDなのか。

漸くここで先ほど調べた、metaobjectの定義IDが必要となります。
「metaobjectのid」ではなく「metaobjectの定義id」という点に注意してください。

## mutationを実行 (metafieldを作成する)

これでmutationとvariablesが整ったので実行すればshopにmetafieldが作成されます。

では本当に定義できているのか確認してみましょう。

``` graphQL
{
    shop {
        metafield(namespace:"hoge",key:"fuga") {
          id
        }
	}
}
```

これで戻り値がnullでなければshopにmetafieldの定義ができていることになります。

では次にこのmetafieldにmetaobjectのエントリーを設定していきます。

## metafieldに値を設定する

それではshopに定義したmetafieldにmetaobjectのエントリーを設定していきます。

ここでも必要なmutationは [リファレンス](https://shopify.dev/docs/api/admin-graphql/2024-04/mutations/metafieldsSet) よりコピーしてきます。

``` graphQL
mutation MetafieldsSet($metafields: [MetafieldsSetInput!]!) {
  metafieldsSet(metafields: $metafields) {
    metafields {
      key
      namespace
      value
      createdAt
      updatedAt
    }
    userErrors {
      field
      message
      code
    }
  }
}
```

そしてVariablesの雛形も持ってきて適宜書き換えます。

``` javascript
{
  "metafields": [
        {
        "namespace": "hoge",
        "key": "fuga",
        "ownerId": "gid://shopify/Shop/***********",
        "type": "metaobject_reference",
        "value": "gid://shopify/Metaobject/***********"
        }
	]
}
```

metafieldのnamespace,keyは先ほど設定した値を、ownerIdは取得したshopのidを設定します。

そして「type」について、今回は「metaobject」自体なので「metaobject_refernce」を、
「value」は先に取得しておいた「metaobject」のエントリーidを設定します。
(どちらもmetaobjectの定義ではないので注意してください)

このmutationを実行すれば漸く

「shop」の
「metafield」に
「metaobject」の
「エントリー」が
登録完了になります。

あとはliquidなりで必要な時に取得して使うことができます。

``` liquid
{{ shop.metafields.hoge.fuga.value }}
```