カートに入れました

gatsby-starter-blogのブログ投稿記事にsns共有ボタン設置

gatsby-starter-blogをカスタムする。今回は投稿記事を簡単にsnsで共有できるようにボタンを設置し、共有時の情報を設定する

パッケージインストール

必要なのはreact-shareというもの

$ yarn add react-share

実装

共有ボタンを設置するのは投稿記事にする

src/templates/blog-post.jsを編集していく

追加する部分は生地とフッターの間に、

graphqlのsiteMetadataにsiteUrl項目

import * as React from "react"
import { Link, graphql } from "gatsby"
import _ from "lodash"

import Bio from "../components/bio"
import Layout from "../components/layout"
import Seo from "../components/seo"
import ShareSns from "../components/share-sns"

const BlogPostTemplate = ({ data, location }) => {
  const post = data.markdownRemark
  const siteTitle = data.site.siteMetadata?.title || `Title`
  const { previous, next } = data

  return (
...
    <section
        dangerouslySetInnerHTML={{ __html: post.html }}
        itemProp="articleBody"
    />
    {/* 日本語を含むためエンコードする */}
    <ShareSns title={post.frontmatter.title} url={encodeURI(`${data.site.siteMetadata?.siteUrl}${post.fields.slug}${post.frontmatter.title}`)} />
    <hr />
    <footer>
        <Bio />
    </footer>
...

export const pageQuery = graphql`
  query BlogPostBySlug(
    $id: String!
    $previousPostId: String
    $nextPostId: String
  ) {
    site {
      siteMetadata {
        title
        siteUrl
      }
    }
...

ShareSnsコンポーネントは

import React from 'react'
import styled from '@emotion/styled'
import {
  FacebookIcon,
  FacebookShareButton,
  HatenaIcon,
  HatenaShareButton,
  LineIcon,
  LineShareButton,
  TwitterIcon,
  TwitterShareButton
} from 'react-share'

const Wrapper = styled.div`
  display: flex;
  padding-bottom: 24px;
`

const ButtonWrapper = styled.div`
  padding-right: 12px;
`

const ShareSns = ({title, url}) => {
  return (
    <Wrapper>
      <ButtonWrapper>
        <FacebookShareButton url={url}>
          <FacebookIcon size={40} round />
        </FacebookShareButton>
      </ButtonWrapper>

      <ButtonWrapper>
        <LineShareButton url={url} >
          <LineIcon size={40} round />
        </LineShareButton>
      </ButtonWrapper>

      <ButtonWrapper>
        <TwitterShareButton title={title} url={url} >
          <TwitterIcon size={40} round />
        </TwitterShareButton>
      </ButtonWrapper>

      <ButtonWrapper>
        <HatenaShareButton url={url} >
          <HatenaIcon size={40} round />
        </HatenaShareButton>
      </ButtonWrapper>
    </Wrapper>
  )
}

export default ShareSns

表示させると

OGP設定

  • OGP(Open Graph Protocol)とは

OGPとは「Open Graph Protcol」の略で、FacebookやTwitterなどのSNSでシェアした際に、設定したWEBページのタイトルやイメージ画像、詳細などを正しく伝えるためのhtml要素

react-helmetがパッケージに入っていないのならインストールする。

gatsby-starter-blogには初めから入っていて設定もある程度してある

画像の設定はしていないので今回は画像設定をする

import * as React from "react"
import PropTypes from "prop-types"
import { Helmet } from "react-helmet"
import { useStaticQuery, graphql } from "gatsby"

import defaultOgpImage from "../images/default-ogp-image.png";

const Seo = ({ description, lang, meta, title, image}) => {
  const { site } = useStaticQuery(
    graphql`
      query {
        site {
          siteMetadata {
            title
            siteUrl
            description
            social {
              twitter
            }
          }
        }
      }
    `
  )

  const metaDescription = description || site.siteMetadata.description
  const defaultTitle = site.siteMetadata?.title
  const ogpImage = image ? `${site.siteMetadata.siteUrl}${image.images.fallback.src}` : `${site.siteMetadata.siteUrl}${defaultOgpImage}`

  return (
    <Helmet
      htmlAttributes={{
        lang,
      }}
      title={title}
      titleTemplate={defaultTitle ? `%s | ${defaultTitle}` : null}
      meta={[
        {
          name: `description`,
          content: metaDescription,
        },
        {
          property: `og:title`,
          content: title,
        },
        {
          property: `og:description`,
          content: metaDescription,
        },
        {
          property: `og:image`,
          content: ogpImage,
        },
        {
          property: `og:type`,
          content: `website`,
        },
        {
          name: `twitter:card`,
          content: `summary_large_image`,
        },
        {
          name: `twitter:creator`,
          content: site.siteMetadata?.social?.twitter || ``,
        },
        {
          name: `twitter:title`,
          content: title,
        },
        {
          name: `twitter:description`,
          content: metaDescription,
        },
        {
          property: `twitter:image`,
          content: ogpImage,
        },
      ].concat(meta)}
    />
  )
}

Seo.defaultProps = {
  lang: `jp`,
  meta: [],
  description: ``,
}

Seo.propTypes = {
  description: PropTypes.string,
  lang: PropTypes.string,
  meta: PropTypes.arrayOf(PropTypes.object),
  title: PropTypes.string.isRequired,
}

export default Seo

Seoコンポーネントにimageの引数を持たせるようにし、そのimageを

const ogpImage = image ? `${site.siteMetadata.siteUrl}${image.images.fallback.src}` : `${site.siteMetadata.siteUrl}${defaultOgpImage}`

絶対パスに変換し

{
  property: `og:image`,
  content: ogpImage,
},

セットする

 {
    name: `twitter:card`,
    content: `summary_large_image`,
  },

contentをsummary_large_imageにする。summaryだと小さい画像になる

これでシェア投稿に画像がつく

確認

  • はまりポイントはlocalhostで確認ができない、本番環境に上げて確認する
  • Card validatorというサイトでイメージの確認をすることができる

インデックスページでは画像がつくけど、ブログページではメタタグが見つからないとなってしまう。。

ブラウザで確認してもメタタグはついている。。謎

URLが長すぎるとダメ?短いURLならうまくいった

参考 :