Shopifyのメタオブジェクト

窓辺

少し試したことをメモとして。
便利ではあるものの分かりづらく面倒なところがあるという印象です。

[追記:2025.2.20]
メタオブジェクトとエントリーの最大数とメタフィールドで参照として扱う場合を追加。

参考情報

イメージ


shop
- metaobjects
-- metaobject
--- type.handle
--- type.handle
--- type.handle

上記のようにグローバルオブジェクトともいえるshopオブジェクト内に配置されているので、ストアのどこからでもアクセス可能です。

通常のメタフィールドとは違いmetaobjectsmetaobjectを複数格納する前提なので、末尾にvaluesをつけてforで出力するか、対象のtypehandleを特定してアクセスする必要があります。

metaobjectがエントリーに該当します。

テーマエディタでの使用

テーマエディタにて、メタフィールドと同様にメタオブジェクトを選び動的ソースで接続できます。

各ページのメタフィールドとは違い多くの場所で使用可能ですが、当然ながら入力欄のタイプに対応した場合しか設定できません。
具体的には、リッチテキストの入力欄に、画像やページや商品のメタオブジェクトを設定することはできません。

サンプル


[前提]
Type: foo (Settings>Custom dataのMetaobjectsで定義として追加)
Handle: bar (追加した定義にfieldとして追加)
Name(key?): baz (追加したfieldのName)
field type: Single line text

上記前提で以下のようになります。

typeのみを指定して出力


forで出力(valuesが必要)
{% for obj in shop.metaobjects.foo.values %}
  {{ obj.baz }}
{% endfor %}

出力順序変更

forを使うと古いエントリーの方から順に出力されます。
現時点(2024.4)ではエントリーの順序をドラッグ&ドロップで変更できないため、順番変更用のメタフィールドを追加しsortフィルターを使う必要があると思います。

ただし下記投稿のように数値でのソートはできないため、順番変更用のメタフィールドは「Single line text(単一行のテキスト)」など文字列が追加できるものを選ぶ必要があります。

また、sortフィルターを使用するには一旦変数に入れる必要もあり、まとめると以下のようになります。


順番設定用にSingle line textで"order"を追加した前提
{% assign metaobject_values = shop.metaobjects.foo.values %}
{% assign metaobject_values_array = metaobject_values | sort: 'order' %}
{% for obj in metaobject_values_array %}
  {{ obj.baz }}
{% endfor %}

type/handle/を指定して出力


直接type/handle/を指定して出力
{{ shop.metaobjects.foo.bar.baz.value }}

forで出力(valuesとvalueが必要)
{% for obj in shop.metaobjects.foo.bar.values %}
  {{ obj.baz.value }}
{% endfor %}

メタオブジェクトに対してpaginateが使用可能

上記を見て知りましたが、下記のようにpaginateでページングが可能です。


{% paginate shop.metaobjects.foo.bar.values by 5 %}
  {% for obj in shop.metaobjects.foo.bar.values %}
    {{ obj.baz.value }}
  {% endfor %}
  {{ paginate | default_pagination }}
{% endpaginate %}

{{ paginate | default_pagination }}で移動できる2ページ目以降には、URL末尾にパラメータが追加された状態となります。

このページングのためにJSやliquidを新たに用意する必要はなく、通常のcollectionで用いるような方法で利用できるようです。

なお、把握している範囲ではliquidのみで51以上のエントリーを取得する方法はpaginateタグを使うしかないようです。

この際の注意点としては、sortwhereなどのフィルターを使うとページングが機能しなくなる点が挙げられます。

要件としてエントリー数が51以上の場合にも対応する場合は対応が難しくなり、個人的に案件で用いた方法としては擬似的な2次元配列を作ることで対応しました。

メタフィールドのlistタイプには使用できない

配列であるメタフィールドのlistタイプに対してpaginateを使用してもエラーになります。

メタオブジェクトとエントリーの最大数

上記のように上限が設定されています。
PlusとEnterprise以外の上限は64個であり、気軽にメタオブジェクトを増やすと痛い見る可能性が高まりそうなので工夫が必要かもしれません。

なお、上記では不明点があったのでサポートに質問したところ以下のような情報をいただけましたので引用します。

◾️メタオブジェクト定義(Metaobject Definitions)の最大数:

プラン 最大定義数
Shopify Plus 128個
その他全プラン 64個

注: Starterプランではメタオブジェクトは利用できません

メタオブジェクトエントリー(Entries)の最大数(ストア全体):

プラン 最大エントリー数
Shopify Plus 128,000個
その他全プラン 64,000個

その他の重要な制限:

  • APIでのページネーション制限: 30,000エントリー
  • 1リクエストあたりの取得数: 1,000エントリー/タイプ
  • Liquidでのハンドル参照: 1つの定義につき最大20エントリーまで
    例: shop.metaobjects[type][handle]の形式で参照する場合
  • 回避策: メタフィールド経由での参照は制限対象外

重要なのは以下の点だと思います。

  • Liquidでのハンドル参照: 1つの定義につき最大20エントリーまで
    例: shop.metaobjects[type][handle]の形式で参照する場合
  • 回避策: メタフィールド経由での参照は制限対象外

試したところ次項のように参照経由でメタオブジェクトを扱う方法で20以上のエントリーを取得し扱えることを確認しました。

メタフィールドでメタオブジェクトを参照して用いる


■メタオブジェクト
- タイプ: foo
- フィールド(一行テキスト): title
- フィールド(ファイル): image

■エントリー
前項で設定したフィールドに値を設定

■メタフィールド
「設定 > メタフィールドおよびメタオブジェクト > コレクション」で「コレクションのメタフィールドの定義」画面に移動し、「タイプを選択」でメタオブジェクトを選ぶ。
前項のメタオブジェクトを選び、「エントリーのリスト」を選んで保存。
任意のコレクション投稿画面に移動し、設定した参照のメタオブジェクトを選びエントリーを複数選ぶ

上記の前提で以下コードによってエントリーの値が出力されるはずです。
-----------------------

{% assign entries = collection.metafields.custom.foo.value %}
<ul>
{% for entry in entries %}
<li>{{ entry.title }}<br>{{ entry.image | image_url: width: 200 | image_tag }}</li>
{% endfor %}
</ul>

collection.metafields.custom.foo.valuejsonフィルターで出力したところ単純な配列のようになっていたため、以下のような理解で良いのかなと思います。

  • メタフィールドでメタオブジェクトのようなデータを参照で選ぶと、選択したエントリーのキーと値が配列として保存される
  • 前項の処理により、出力時にメタオブジェクトの存在は気にせずとも良い

上記の処理が「メタフィールド経由での参照は制限対象外」という部分に該当するのだと思います。

結び

管理画面的には、Settings > Custom DataとContent > Metaobjectの両方から同じ画面(Settingsの方の画面)に到達するので、便利なようでわかりづらく感じました。
どちらからでも同じ画面に到達できることがわかれば混乱せずに済みますが、慣れないうちはUIが似た別の画面なのではと多少迷いました。

とはいえ便利な仕組みであることは確かです。

4人がこの記事を評価

役に立ったよという方は上の「記事を評価する」ボタンをクリックしてもらえると嬉しいです。

連投防止のためにCookie使用。SNSへの投稿など他サービスとの連動は一切ありません。

コメント欄