ソーシャル系のサービスへ記事をシェアするボタンは開発者用のページを参照すればすぐに実装できますが、デザインの仕様としてカスタマイズが必要な場合はそこそこ面倒な実装が必要になります。
この記事では、それぞれの実装についてまとめているので、Gatsbyでソーシャルシェアボタンを実装するときに参考にしてみてください。
今回紹介するシェアボタンは下記です。
下記のサイトを踏まえて、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;
コード自体は少し省略しています。
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の取得をすべしとあるので、 onRenderBody
の setPreBodyComponents
に設定しています。
ちなみに、Gatsbyで head
や body
をカスタマイズするためにはビルド時に html.js
の生成コードをカスタマイズすることが必要になります。
それぞれのカスタマイズ次第で構成は変わりますが、テンプレートとなる形で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のシェアボタンをカスタマイズで使用する時はTwitterのSDKは必要ないのですが、Tweetを埋め込みしたい場合やなどいろいろと便利なPluginがあるので、入れておいて損はないです。
gatsby-plugin-twitter | gatsbyjs/gatsby
$ yarn add -D gatsby-plugin-twitter
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のメタデータと統合して設定するようにしています。そこは各々のファイルでカスタマイズしていってください。
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のシェアボタンのファイルと統合するようにしてください。
他のシェアボタンと似たように実装してもらえれば大丈夫です。
hatenaShare = () => {
const url = new URL("https://b.hatena.ne.jp/entry/panel/");
url.searchParams.set("url", link);
window.open(url.toString());
}
他のシェアボタンと似たように実装してもらえれば大丈夫です。
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());
}
Shintaro Kaneko
November 06, 2020