microCMS

拡張フィールド(iframe連携)でGoogle Mapsと連携し、「地図フィールド」を実現する

ひまらつ

こんにちは。ひまらつです。

microCMSには「テキスト」「リッチエディタ」「数値」など、さまざまな種類のフィールドが用意されています。
コンテンツに合わせて最適なものを選べるようになっていますが、その一つに「拡張フィールド」があるのはご存知でしょうか?

拡張フィールドは、iframeを利用して外部のデータと連携するためのフィールドです。
例えば自社のデータベースと連携したり、APIを使って外部サービスと連携したりなどが実現できます。

この記事では拡張フィールドを利用し、地図系のコンテンツを扱う方法を紹介します。

2025年5月7日 追記

※この記事は、2025年5月7日に内容をアップデートしました。
実装方法を microcms-field-extension(SDK)ベースに刷新し、Google Maps Platformとの連携方法などもアップデートしています。

1. 今回つくるもの:地図フィールド

拡張フィールド連携を使って、以下のようにコンテンツを入稿できます(動画):

上の動画ではマップから地点を選択してデータを入稿しています。
例えば東京タワーの地点を選択すると、microCMSのAPIレスポンスは次のようになります。

{
    "id": "k_zvavx33",
    "createdAt": "2025-05-01T01:38:04.307Z",
    "updatedAt": "2025-05-01T01:38:04.307Z",
    "publishedAt": "2025-05-01T01:38:04.307Z",
    "revisedAt": "2025-05-01T01:38:04.307Z",
    "name": "東京支店",
    "location": {
        "lng": 139.7454329,
        "lat": 35.6585805,
        "address": "日本、〒105-0011 東京都港区芝公園4丁目2−8"
    }
}

location の中身がマップで選択した地点のデータになっています。

この「地図フィールド」はどういったシーンで役立つでしょうか?
例えば店舗一覧のページを作る場合、

  • 「店舗名」
  • 「住所」
  • 「緯度・経度」

がデータとして必要になりますが、これを自分で調べて入力するのは手間ですよね。
microCMSの管理画面内でマップを選択して入稿が完結すれば、業務の効率は大幅に改善します。

それでは、実際にどのようにデータ連携を実装しているのか、コードを交えて紹介していきます。

2. 拡張フィールド連携の仕組み

拡張フィールド連携では、iframeとmicroCMS管理画面の間で window.postMessage を使って値のやり取りを行います。
図にすると次のような流れになります。

今回はGoogle Mapsと連携させたいので、まずGoogle Maps Platform APIを使った地図ページを作成します。
このページではクリックした地点の情報を取得する機能に加え、利便性向上のために簡単な地点検索も実装しておきます。

そしてその地図ページを拡張フィールドでmicroCMSと連携させます。
マップで選んだ座標や住所がmicroCMSのAPIから取得できるようになります。

3. 地図ページを作る

まずは地図ページの実装です。ここではVite + Reactのプロジェクトを新規に作成して進めていきます。
このパートはmicroCMSからは独立した部分ですので、興味のない方は「4. microCMSとデータ連携する」までスキップしていただいて構いません。

プロジェクトを作成する

ViteのGetting Startedページに沿って進めていきます。


いくつか項目を聞かれるので以下のように選択します。

  • プロジェクト名:iframe-sample
  • フレームワーク:react
  • 種類:TypeScript


プロジェクトが作成されます。
yarn dev を実行して開発サーバーを立ち上げたら、ブラウザでhttp://localhost:5173 にアクセスしましょう。

このようなサンプルページが表示されるはずです。

それではsrc/App.tsx のファイルを編集して、地図ページを実装していきましょう。

Google Mapsを表示する

まず、Google Maps Platformにて、以下の設定を行ってください。

  1. Google Cloud プロジェクトをセットアップする
  2. API キーを作成する
  3. (必要に応じて、各APIを有効にする)


Google Mapsを扱うために @react-google-maps/api を利用します。

yarn add @react-google-maps/api

Google Mapsを表示します。

// src/App.tsx
import { useEffect, useState, useCallback } from "react";
import { GoogleMap, Marker, useJsApiLoader } from "@react-google-maps/api";
import './App.css';

const containerStyle = {
  width: "100%",
  height: "100vh",
};

const defaultCenter = {
  lat: 35.69575,
  lng: 139.77521,
};

const defaultZoom = 9;

const App = () => {
  const [mapCenter, setMapCenter] = useState(defaultCenter);
  const [zoom, setZoom] = useState(defaultZoom);

  const { isLoaded } = useJsApiLoader({
    id: "google-map-script",
    googleMapsApiKey: <YOUR-GOOGLE-MAPS-API-KEY>,
    libraries: ["places"],
    language: "ja",
    region: "JP",
  });
  return (
    <div className="App">
      {isLoaded && (
        <GoogleMap
          mapContainerStyle={containerStyle}
          center={mapCenter}
          zoom={zoom}
          options={{
            zoomControl: true
          }}
        />
      )}
    </div>
  );
};

export default App;

<YOUR-GOOGLE-MAPS-API-KEY> には先ほど取得したAPIキーを設定してください。

ページを表示してみて、地図が表示されていればOKです。

クリックした地点にマーカーを立てる

マップ上でクリックされた場所の地点を保持し、その場所にマーカーを立てます。

まずは値を保持するためのステートを用意します。

const [locationData, setLocationData] = useState<LocationData | null>(null);

先ほどのGoogle Mapsの部分を以下のように変更します。

<GoogleMap
  mapContainerStyle={containerStyle}
  center={mapCenter}
  zoom={zoom}
  onClick={handleMapClick}
  options={{
    zoomControl: true
  }}
>
  {locationData && (
    <Marker
      position={{
        lat: locationData.lat,
        lng: locationData.lng,
      }}
    />
  )}
</GoogleMap>

マップクリックに呼ばれる関数は以下のように宣言します。

const handleMapClick = useCallback(
  (event: google.maps.MapMouseEvent) => {
    if (!event.latLng) return;

    const geocoder = new window.google.maps.Geocoder();
    geocoder.geocode({ location: event.latLng }, (results, status) => {
      if (status === "OK" && results?.[0]) {
        const result = results[0];
        const newLocation: LocationData = {
          address: result.formatted_address,
          lat: result.geometry.location.lat(),
          lng: result.geometry.location.lng(),
        };
        setLocationData(newLocation);
      }
    });
}, []);


ここまで実装すると、マップをクリックしてマーカーが立つようになっているはずです。

地点の検索機能を追加する

マップをスクロールして場所を探すのは大変なので、地点名から検索してジャンプする機能をつけましょう。

まずはクエリのステートを定義します。

const [query, setQuery] = useState("");

このような形でViewをつくり、

<div id="data-search-area">
  <input
    className="input"
    type="text"
    value={query}
    onChange={handleChange}
    onKeyDown={handleKeyDown}
  />
  <button className="search" onClick={handleSubmit}>
    検索
  </button>
</div>


地点名から住所や緯度経度を取得するための処理を geocode として宣言します。

const geocode = () => {
  if (!query) return;

  const geocoder = new window.google.maps.Geocoder();
  geocoder.geocode({ address: query }, (results, status) => {
    if (status === "OK" && results?.[0]) {
      const result = results[0];
      const newLocation: LocationData = {
        address: result.formatted_address,
        lat: result.geometry.location.lat(),
        lng: result.geometry.location.lng(),
      };
      setLocationData(newLocation);
      setMapCenter({ lat: newLocation.lat, lng: newLocation.lng });
      setZoom(15);
    }
  });
};


「検索」ボタンをクリックしたときに geocode を呼びましょう。

const handleSubmit = () => {
  geocode();
};

const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
  setQuery(event.target.value);
};

const handleKeyDown = (event: React.KeyboardEvent<HTMLInputElement>) => {
  if (event.key === "Enter") {
    geocode();
  }
};


App.css に以下の行を足して見た目を少しだけ整えます。

// App.css
#data-search-area {
  margin: 10px 0;
}
input.input {
  width: 240px;
  height: 24px;
  margin: 0 10px;
}
button.search {
  height: 30px;
}


地点を検索できるようになりました。

指定した地点の緯度・経度と住所を表示する

指定した地点の情報がわかりやすいように、緯度・経度と住所を表示します。

return 
(
  <div className="App">
      // 追加
      {locationData && (
        <div id="data-info-area">
          <div>
            <strong>指定した地点:</strong>
            {locationData.lat}, {locationData.lng}
          </div>
          <div>
            <strong>住所:</strong>
            {locationData.address}
          </div>
        </div>
      )}
      ...
  </div>
);


App.css に以下を追記します。

// App.css
#data-info-area{
  margin-bottom: 8px;
  font-size: 14px;
}


緯度・経度と住所を表示できるようになりました。

これで地図ページの実装は完了です。
このページをmicroCMSと繋ぎ込んでいきましょう。

4. microCMSとデータ連携する

microCMSの拡張フィールドでは、microcms-field-extension(SDK) を活用することで、iframe内から安全かつ簡潔にデータ連携を実現できます。

パッケージのインストール

React Hooksベースのライブラリであるmicrocms-field-extension-reactを利用して、マップと連携する拡張フィールドのデータ送受信処理を実装していきます。
まずはパッケージをインストールします。

yarn add microcms-field-extension-react


以下のようにインポートして使います。

import { useFieldExtension } from "microcms-field-extension-react";

このフックを使うことで、初期値の取得やデータの送信、iframeフィールド高さ・幅の設定など、microCMSとのやりとりを簡潔に実装できます。

useFieldExtension のセットアップ

まずは useFieldExtension フックを使って、拡張フィールドの初期設定を行います。引数には初期値(今回は null)とオプションを渡します。

const { data, sendMessage } = useFieldExtension<LocationData | null>(null, {
  origin: "<YOUR-SERVICE-ID>.microcms.io", // microCMSの管理画面URL
  height: 600,
  width: "100%",
  onPostSuccess: () => console.log("microCMSにデータを連携しました"),
  onPostError: () => console.log("送信に失敗しました"),
});

<YOUR-SERVICE-ID>には、ご利用のサービスIDを入力してください。

SetupOption の主なオプション

origin

https://<YOUR-SERVICE-ID>.microcms.io を指定(セキュリティのため必須)

height / width

iframeフィールドの初期サイズを設定

onPostSuccess

sendMessage() 成功時のコールバック処理

onPostError

sendMessage() 失敗時のコールバック処理

※詳しくは以下の記事を参考にしてください
拡張フィールドを簡単に作れるSDKとテンプレートを公開しました | microCMSブログ

地図の選択地点が変わったらmicroCMSに伝える

ユーザーが地図をクリックしたり、検索を行って地点を指定したときは、Google Mapsのジオコーダーを使って住所と緯度・経度を取得し、そのデータを sendMessage()を通じて microCMSに渡します。

const handleMapClick = useCallback(
  (event: google.maps.MapMouseEvent) => {
    if (!event.latLng) return;

    const geocoder = new window.google.maps.Geocoder();
    geocoder.geocode({ location: event.latLng }, (results, status) => {
      if (status === "OK" && results?.[0]) {
        const result = results[0];
        const newLocation: LocationData = {
          address: result.formatted_address,
          lat: result.geometry.location.lat(),
          lng: result.geometry.location.lng(),
        };
        setLocationData(newLocation);
        setMapCenter({ lat: newLocation.lat, lng: newLocation.lng });
        setZoom(15);
        sendMessage({ data: newLocation }); // microCMSへ送信
      }
    });
  },
  [sendMessage]
);

const geocode = () => {
  if (!query) return;

  const geocoder = new window.google.maps.Geocoder();
  geocoder.geocode({ address: query }, (results, status) => {
    if (status === "OK" && results?.[0]) {
      // ... (略)
      setLocationData(newLocation);
      setMapCenter({ lat: newLocation.lat, lng: newLocation.lng });
      setZoom(15);
      sendMessage({ data: newLocation });
    }
  });
};

保存してあるデータがあれば初期表示に反映させる

以下のように useEffect フックを使って、保存済みデータがあるかをチェックし、あればマーカーと地図の中心位置に反映するようにします。data useFieldExtension() から取得した値になります。

useEffect(() => {
  if (data) {
    setLocationData(data);
    setMapCenter({ lat: data.lat, lng: data.lng });
    setZoom(defaultZoom);
  }
}, [data]);

この処理により、編集画面を開いたときに以前選択した場所がマップ上に再表示され、再編集もしやすくなります。

データ連携のフィードバックを表示する

送信の成否に応じてフィードバックを表示する場合は、SetupOption 内で onPostSuccess, onPostError を指定しておくと便利です。今回は react-hot-toast を使ってトースト通知を出しています。

import toast, { Toaster } from "react-hot-toast";

const { data, sendMessage } = useFieldExtension<LocationData | null>(null, {
  // ... (略)
  onPostSuccess: () => toast.success("microCMSに送信しました"),
  onPostError: () => toast.error("送信に失敗しました"),
});


Toast表示を追加します。

return 
(
  <div className="App">
      // 追加
      <Toaster position="top-right" toastOptions={{ duration: 1000 }} />
      ...
  </div>
);

microCMSへのデータ送信が成功したタイミングでトーストが表示されるようになりました。

これでmicroCMSとのデータ連携を実装できました。

5. microCMS管理画面から使ってみよう

作成したページをmicroCMSと連携しましょう。

APIスキーマを定義する

APIを新しく作成します。

フィールドの種類で「拡張フィールド」を選択します。

モーダルが表示されるのでURLを入力します。
サーバーにホスティングしているURLでも構いませんし、localhost を指定することもできます。


これでAPIが準備できたので、コンテンツを追加してみましょう。
入稿画面を見ると「場所」の項目には自作したWebサイトがiframeで表示されています。

地点を選択してみます。例えば「東京タワー」で検索して、位置情報を取得しました。

コンテンツを公開するとAPIのレスポンスは以下のようになります。

{
    "id": "k_zvavx33",
    "createdAt": "2025-05-01T01:38:04.307Z",
    "updatedAt": "2025-05-01T01:38:04.307Z",
    "publishedAt": "2025-05-01T01:38:04.307Z",
    "revisedAt": "2025-05-01T01:38:04.307Z",
    "name": "東京支店",
    "location": {
        "lng": 139.7454329,
        "lat": 35.6585805,
        "address": "日本、〒105-0011 東京都港区芝公園4丁目2−8"
    }
}

地図で選択した地点の lnglataddress が取得できていることが確認できます。
これでmicroCMSとGoogle Mapsが連携でき、「地図フィールド」を自作できました。

最後に

拡張フィールドを使って外部のデータと連携する方法を紹介しました。
連携するためのページを自分で作る必要があるなど技術的なスキルは求められますが、外部のデータと繋げる大きな可能性があると思います。

拡張フィールドを試して何か作った際には、ぜひTwitterなどで教えてください!

まずは、無料で試してみましょう。

APIベースの日本製ヘッドレスCMS「microCMS」を使えば、 ものの数分でAPIの作成ができます。

microCMSを無料で始める

microCMSについてお問い合わせ

初期費用無料・14日間の無料トライアル付き。ご不明な点はお気軽にお問い合わせください。

お問い合わせ

microCMS公式アカウント

microCMSは各公式アカウントで最新情報をお届けしています。
フォローよろしくお願いします。

  • X
  • Discord
  • github

ABOUT ME

ひまらつ
SwiftやPythonやスプラトゥーンを楽しんでます