Gatsbyでソーシャルシェアボタンを実装する

#Programming#Technology

ソーシャル系のサービスへ記事をシェアするボタンは開発者用のページを参照すればすぐに実装できますが、デザインの仕様としてカスタマイズが必要な場合はそこそこ面倒な実装が必要になります。

この記事では、それぞれの実装についてまとめているので、Gatsbyでソーシャルシェアボタンを実装するときに参考にしてみてください。

今回紹介するシェアボタンは下記です。

  • Facebook
  • Twitter
  • はてなブックマーク
  • LinkedIn

Facebook

Adding Page Metadata

下記のサイトを踏まえて、Facebookシェアをするにあたって必要なメタデータを実装しています。

import React from "react";
import { Helmet } from "react-helmet";
import { format } from "util";
import get from "lodash/get";

const SEO = ({ title, description, image, article }) => {
  const { pathname } = useLocation();
  const siteMetadata = get(useStaticQuery(query), "site.siteMetadata");

  const seo = {
    title: title || siteMetadata.title,
    titleTemplate: siteMetadata.titleTemplate,
    description: description || siteMetadata.description,
    image: image || siteMetadata.image,
    url: `${siteMetadata.siteUrl}${pathname}`,
  };

  return (
    <Helmet title={seo.title} titleTemplate={seo.titleTemplate}>
      {seo.url && <meta property="og:url" content={seo.url} />}
      <meta property="og:type" content={article ? "article" : "website"} />
      {seo.title && <meta property="og:title" content={format(seo.titleTemplate, seo.title)} />}
      {seo.description && <meta property="og:description" content={seo.description} />}
      {seo.image && <meta property="og:image" content={seo.image} />}
    </Helmet>
  );
};

export default SEO;

コード自体は少し省略しています。

Load Facebook SDK on SSR

Facebook SDKを実装するにあたり、サイトには様々な情報がありますが今回はカスタマイズをするための実装をするための設定を行います。デフォルトのシェアボタンを使う場合はもっと簡単に実装できます。

const facebookSdkOptions = {
  appId: "[YOUR-FACEBOOK-APP-ID]",
  autoLogAppEvents: true,
  xfbml: true,
  version: "v8.0",
};

exports.onRenderBody = ({ setPreBodyComponents }) => {
  setPreBodyComponents([
    <script
      key="facebook-async-init"
      dangerouslySetInnerHTML={{
        __html: `window.fbAsyncInit = function() {FB.init(${JSON.stringify(facebookSdkOptions)})}`,
      }}
    />,
    <script
      key="facebook-sdk"
      async={true}
      defer={true}
      crossOrigin="anonymous"
      src="https://connect.facebook.net/en_US/sdk.js"
    ></script>,
  ]);
};

GatsbyのSSRで必要なSDKの取得と初期化を行っています。Facebook SDKはBodyの先頭にSDKの取得をすべしとあるので、 onRenderBodysetPreBodyComponents に設定しています。

Deep Dive for Customizing html.js

ちなみに、Gatsbyで headbody をカスタマイズするためにはビルド時に html.js の生成コードをカスタマイズすることが必要になります。

Embed Facebook Share Button

それぞれのカスタマイズ次第で構成は変わりますが、テンプレートとなる形でReactのコンポーネントを定義しておきます。

import React from "react";
import { useLocation } from "@reach/router";
import get from "lodash/get";

class PostsTemplate extends React.Component {
  render() {
    const { pathname } = useLocation();
    const siteMetadata = get(props, "data.site.siteMetadata");

    const facebookShare = () => {
      FB.ui({
        display: "popup",
        method: "share",
        href: `${siteMetadata.siteUrl}${pathname}`,
      });
    };

    return (
      <div className="facebook-share-button" role="button" onClick={facebookShare} />
    );
  };
};

もしも、TypeScriptを使っている場合は yarn add -D @types/facebook-js-sdk をしてタイプを拾えるようにしてください。

Twitter

Add Plugin for Tweet

Twitterのシェアボタンをカスタマイズで使用する時はTwitterのSDKは必要ないのですが、Tweetを埋め込みしたい場合やなどいろいろと便利なPluginがあるので、入れておいて損はないです。

gatsby-plugin-twitter | gatsbyjs/gatsby

$ yarn add -D gatsby-plugin-twitter

Adding Page Metadata

Twitter Cardsにて情報を取得するためのメタデータの設定は書きにあるので必要なやつを設定しておきます。

import React from "react";
import { Helmet } from "react-helmet";
import { format } from "util";
import get from "lodash/get";

const SEO = ({ title, description, image, twitterUsername }) => {
  const { pathname } = useLocation();
  const siteMetadata = get(useStaticQuery(query), "site.siteMetadata");

  const seo = {
    title: title || siteMetadata.title,
    titleTemplate: siteMetadata.titleTemplate,
    description: description || siteMetadata.description,
    image: image || siteMetadata.image,
    url: `${siteMetadata.siteUrl}${pathname}`,
  };

  return (
    <Helmet title={seo.title} titleTemplate={seo.titleTemplate}>
      {twitterUsername && <meta name="twitter:creator" content={twitterUsername} />}
      <meta name="twitter:card" content="summary_large_image" />
      {seo.title && <meta name="twitter:title" content={format(seo.titleTemplate, seo.title)} />}
      {seo.description && <meta name="twitter:description" content={seo.description} />}
      {seo.image && <meta name="twitter:image" content={seo.image} />}
    </Helmet>
  );
};

export default SEO;

実装はFacebookのメタデータと統合して設定するようにしています。そこは各々のファイルでカスタマイズしていってください。

Embed Twitter Share Button

import React from "react";
import { useLocation } from "@reach/router";
import get from "lodash/get";

class PostsTemplate extends React.Component {
  render() {
    const { pathname } = useLocation();
    const siteMetadata = get(props, "data.site.siteMetadata");

    const twitterShare = () => {
      const url = new URL("https://twitter.com/intent/tweet");
      url.searchParams.set("hashtags", tags.join(","));
      url.searchParams.set("original_referer", siteMetadata.siteUrl);
      url.searchParams.set("text", title);
      url.searchParams.set("url", link);
      url.searchParams.set("via", twitterUsername);
      window.open(url.toString());
    };

    return (
      <div className="twitter-share-button" role="button" onClick={twitterShare} />
    );
  };
};

このファイルも適宜Facebookのシェアボタンのファイルと統合するようにしてください。

はてなブックマーク

Embed Share Button

他のシェアボタンと似たように実装してもらえれば大丈夫です。

hatenaShare = () => {
  const url = new URL("https://b.hatena.ne.jp/entry/panel/");
  url.searchParams.set("url", link);
  window.open(url.toString());
}

LinkedIn

Embed Share Button

他のシェアボタンと似たように実装してもらえれば大丈夫です。

linkedinShare = () => {
  const url = new URL("https://www.linkedin.com/sharing/share-offsite");
  url.searchParams.set("mini", "true");
  url.searchParams.set("url", link);
  url.searchParams.set("title", article.title);
  window.open(url.toString());
}
B!

Shintaro Kaneko

November 06, 2020