Shopifyのニュースレターの構築が面倒くさかった話

Shopify案件を進めていると、おそらく大体の人がニュースレターの仕組みを実装すると思います。

そんな私も例外ではなくニュースレターの仕組みを導入しました。

やり方としてはShopify側で用意されている構文を使ってフォームを作ります。

デフォルトのテンプレートなんかから引っ張ってきたら 大体コードは載っているのですが、一応備忘録的に最低限のニュースレターフォームのコードを載せておきます。

{% form 'customer' %}
  <input type="hidden" name="contact[tags]" value="newsletter">
  {{ form.errors | default_errors }}
  {% if form.posted_successfully? %}
    <p>{{ 'general.newsletter_form.confirmation' | t }}</p>
  {% else %}
    <label for="email">Email address</label>
    <input type="email"
      class="form-control"
      name="contact[email]"
      id="Email"
      value="{% if customer.email != blank %}{{ customer.email }}{% endif %}"
      placeholder="{{ 'general.newsletter_form.email_placeholder' | t }}"
      autocorrect="off"
      autocapitalize="off">
    <button type="submit" name="commit" id="Subscribe"><span>{{ 'general.newsletter_form.submit' | t }}</span></button>
  {% endif %}
{% endform %}

このまま使うとブサイクになってしまうので、 スタイルなんかはタグを追加するなりしてお好みで調整してみてください。

デフォルトの挙動

Emailを入れてボタンを押すだけですね。

一応デフォルトの挙動としては、ボタンを押した後に「/challenge」というURIに飛ばされ reCAPTCHA(リキャプチャ)というよくスパム防止用の判定に使われるあれが出てきます。

スパムか怪しまれたら画像の中から指定のものを全部選べってやつですね。

reCAPTCHA用のページをカスタマイズしなきゃダメ

おそらくテーマを自作していくと、デフォルトのままだとロゴすら何も見えない状態の reCAPTCHAだけが表示されるページに飛ぶのですごく味気ない状態です。

なんならどこか違うサイトに飛ばされた!?って感じにreCAPTCHAだけが存在するページです。

しかしShopifyのデフォルトテーマにはreCAPTCHA用のディレクトリでもある「/challenge」で使われる 「challenge.liquid」ファイルがどこにも存在していません。

一応自分で作ることによってその「challenge.liquid」ファイルを読み込むことが出来るのですが、 格納する場所は「snippets」ディレクトリの中になるので注意してください。

layoutディレクトリにあるtheme.liquidに分岐を与える

ファイルを作っても結局どここでそのファイルが読み込まれるんだよって思いますよね。

templateディレクトリにあるものはそれぞれで自動的に呼び出されますが、 challengeに関しては特定のURLにきたら条件を分岐してchallenge.liquidを呼び出してやる必要があります。

theme.liquidで本来トップページとかで表示される場所でもある

{{ content_for_layout }}

この部分を読み込むとデフォルトで用意されている味気ないキャプチャ画面のページに飛んでしまいます。

なので以下のような感じで分岐を作ってやる必要があるわけですね

<body>
  {% if request.path == '/challenge' %}
    {% include 'challenge' %}
  {%  elsif request.path == '/en/challenge' %}
    {% include 'challenge' %}
  {% else %}
    {{ content_for_layout }}
    {{ "application.js" | asset_url | script_tag }}
  {% endif %}
</body>

今回私はLangifyを使って英語ページも作っているので「/en」バージョンの分岐も用意しています。

冗長な書き方になっていますが、shopifyって正規表現のif文って使えるんですかね……?

ちゃんと調べてないのでとりあえずゴリ押しで分岐させて作りました。

includeで呼び出すとsnippetsの部分を呼び出すことが出来ます。

challenge.liquidの中身

で、肝心のchallenge.liquidの中身ですがこれまたどうすればいいのかわからなかったので ググってみたら公式のコミュニティ掲示板的なところでこう書けと書いてあったのでそれを流用しました。

<div class="some-wrapper-around-challenge">
  {{ content_for_layout }}  {% comment %} <--- conent_for_layout IS the captcha form in this context {% endcomment %}
  <style>
    /* NOTE: these classes are subject to change at any time... since they are injected by shopify / google captcha */
    .shopify-challenge__container {
    }

    .shopify-challenge__message {
    }

    #g-recapthca {
    }
  </style>
  <script>
    $('shopify-challenge__message').text('Custom message or {{ settings.challenge_message }}')
  </script>
</div>

「challenge」ページでcontent_for_layoutを呼び出すとreCAPTCHAを呼び出すことが出来ます。

iframeではありますが、一応CSSの制御ができますのでここでいい感じにスタイルを調整してやる必要があります。

今回私はその部分のデザインをもらってなかったのでとりあえず同じサイトの証明でもあるロゴを表示して ボタンをそれなりに整えてとりあえずニュースレターを登録できる見た目を構築しました。

その後スパムチェックを突破すれば無事購読者として管理画面に登録されていました。

自由度が高いのはいいんですが、使う側としては運営開始する前にお金払ってんだから こういうのもちゃんと設定画面を準備しとけよとは思いますね……

正直あんまりShopifyを好きになれない感じです。

Sassもテーマに1つのファイルとしてしか構築できないですし、 ディレクトリを作って入れ子にすると認識してくれないので結局Webpackでデザインを作って cssを出力してShopifyの機能であるSassは使わずにやっています。

今回初めてshopifyに携わってみて、この大変さも見積もりに組み込んでおくべきだなとちょっと後悔しております。

今回は勉強代として飲み込みます。

失敗は次回に活かしましょう。

登録後のリダイレクトについて

認証を突破して登録が終わるとトップページにリダイレクトされます。

その際、自動でフォームのところまで画面がスクロールして 「登録ありがとうございました」っていうのが見えてほしいのですが、 今回作っているのが読み込み時にロードアニメがあってロゴのテキストアニメーションがあったりで いわゆるオープニングから始まってしまうので登録できたのかがよくわからない状況でした。

これじゃちょっと不親切すぎるので、リダイレクト時に付与されるGETパラメーターを利用して JavaScriptで無理矢理モーダルダイアログを作って画面の一番手前に来るようにz-indexを弄って リダイレクトされた直後にだけ出現するものを作ってみました。

「?customer_posted=true」というパラメーターがつくので javascriptの「location.search()」でgetのパラメーター部分だけを取得して それを条件にモーダルを出す処理を書けばOKです。

おそらくこういうのをリッチに楽にやるにはShopifyのプラグインを買えって感じなんでしょうかね。

なにかやるたびにお金取られるのもShopifyをあまり好きになれない要因の一つです。

便利っちゃ便利なんですがね。

結局ゴリゴリ自分でコード書くならEC-Cubeのほうが良いんじゃないかと思ってしまいます。

利点としては決済周りの便利さなんでしょうか。

なんにせよECサイト構築はちょっと疲れてたのでシステム開発に集中したくなりました。