(2018/9) Google Mapsの料金体系について

- 2018/9/11 現時点での価格表・FAQに合わせて内容を更新しました。

# Google Mapsの料金体系が変更になります

既にご存じの方も多いと思いますが、**2018年6月11日（アメリカ西海岸時間）**からGoogle Maps APIの料金体系が変更になりました。


![Screen Shot 2018-05-23 at 11.13.35 AM.png](https://qiita-image-store.s3.amazonaws.com/0/39529/9725aa38-234c-f7c7-525b-c81948f87b6f.png)

[Introducing Google Maps Platform](https://mapsplatform.googleblog.com/2018/05/introducing-google-maps-platform.html)

Google Mapチームに直接問い合わせて確認した点も含めて、どう変更になるのかを紐解いて行きます。

# Googleの目的は何？

Googleに確認したところ、今回のアップデートには2つの目的があるそうです。
1. キーなしで使っている人達の追跡
2. Googleも無料で続けることが苦しくなっている

## 1. キーなしで使っている人達の追跡

Google Maps JavaScript API v3の場合、歴史的な理由からAPIキーがなくても地図を表示することが出来ます。
「歴史的な理由」というのは、Google Maps JavaScript API v3が登場した2007年ごろ（だったと記憶）は、
まだAndroidとかiOSとかはそんなに普及してなかったので、IPアドレスとかドメインをベースにアクセス制御ができる時代でした。

ところがAndroidとiOSの普及により時代が変わりました。
モバイルアプリ内でGoogle Maps JavaScript API v3を使うケースが増え、IPアドレスは変動するし、ドメインもないので、
これによって不正な使い方をしている人をGoogleがブロックしたくても、ブロックできないみたいなことが（たぶん）起こっているのが現在です。
これを解消したいというのが一番の目的のようです。

## 2. Googleも無料で続けることが苦しくなっている

地図やストリートビュー・航空写真の更新費用がかなりかかっていて、「無料」を続けるのもなかなか大変みたいです。
それを踏まえてヘビーユーザーを対象に何年か前から料金体系を変更してきていて、今回はそれをもう一歩踏み込んだ形です。
(それでも無料で使わせてくれているGoogleさん、ありがとう)

# 「無料枠」がどう変わるのか？

いままでは**「個別のAPIごとに」それぞれ無料で使える無料枠があり超過分だけを支払う**、という形態でした。
これが**「Google Maps API全体での無料枠」を超えた分だけ支払い**に変更になります。
この「Google Maps API全体での無料枠」というのが、毎月`$200(米国ドル)`までです。
例えば、APIの使用料が`$210`だったら、`$10`の支払いでいいのです。

`$200`のクレジットを受け取るためには、Google APIs Console で課金アカウントを紐付けする必要があります。

この時点では課金されません。
紐付けしない場合は、`$200`のクレジットは貰えません。


# StandardプランとPremiumプラン

- Standardプラン
    今まで無償プランで使っているユーザで、殆どの人はこれに該当します。
    2018年6月11日(日本時間では6月10日)までに、課金を有効にしてください。

- Premiumプラン
    今までGoogleと有償プランの契約を結んでいる企業などです。
    この場合、特に何もする必要がありません。

- その他
　　Googleが特別に許可している非営利団体の場合、引き続き無料です。

# 課金アカウントを有効にしない場合どうなるのか
地図の解像度が下がる（もしくは一部機能が使えなくなる）、または他のAPIではエラーになる、などのことが起こる可能性がある、と書かれています。

# APIキーなしでアクセスし続ける場合、どうなるのか

Google Maps JavaScript API v3の場合、「for development purposes only.」とウォーターマークが表示され、低解像度の地図画像になります。

<img src="https://qiita-image-store.s3.amazonaws.com/0/39529/a4fbce78-f1b2-0691-ce43-243409a7ea5d.png" width="300">

StreetViewの表示はこんな感じになります。
<img src="https://qiita-image-store.s3.amazonaws.com/0/39529/7cbc60f4-0d0b-84cc-5ee4-0d918695c006.png" width="300">


他のAPI(WebServices APIなど)の場合、アクセスが拒否されます。


ただ、機能的にはちゃんと動いてくれますので、「開発時はお金をかけたくない！」という場合には、APIキーを設定しないのも、一つの手段としてはありです。実際、私はそうやってます。


# Google Maps SDK for Android and/or Google Maps SDK for iOSの場合

Google Maps SDK for AndroidとGoogle Maps SDK for iOSを使用している場合、StreetViewを表示していなければ課金を有効にしなくても（今のところ）大丈夫です。
(Google Mapsチームの人は、それでも課金を有効にしておくほうが良い、と言っていました)

# $200でどのくらい使えるのか

Google Maps APIの価格表の日本語版が公開されています。
https://cloud.google.com/maps-platform/pricing/sheet/?hl=ja

ここではその価格表を(2018/9/11現在の)スクリーンショットと共に読み解いていきたいと思います。

## Maps
![Screen Shot 2018-09-11 at 9.59.15 AM.png](https://qiita-image-store.s3.amazonaws.com/0/39529/7447c586-6e87-51a4-fbf8-c43274ca35d4.png)


- Mobile Native Static Maps
    - `Google Maps SDK for Android`と`Google Maps SDK for iOS`には、地図をキャプチャして静的画像データを生成する機能があります。`Mobile Native Static Maps`とは、この機能のことを指します。
    - この機能を使用する場合、無制限に無料ですが、そもそもこの機能は、タイルを生成するためのものではなく、リスト内にGoogleマップのサムネイル表示するためのような使い方なので、この機能でGoogle Maps JavaScript API v3を置き換えられるわけではないです。
- Mobile Native Dynamic Maps
    - `Google Maps SDK for Android`と`Google Maps SDK for iOS`の場合、デバイス内で地図をレンダリングしますので、これを使用する場合、無制限に無料です
- Embed
    - [Google Maps Embed API](https://developers.google.com/maps/documentation/embed/guide)を使用する場合、無制限に無料
    - ただしできることが非常に限られています
    - もし一箇所の地図を表示するだけならオススメです
- Embed Advanced
    - [Google Maps Embed API](https://developers.google.com/maps/documentation/embed/guide)を使用していても「ルート案内」「ストリートビューモード」「検索モード」を使用している場合は、課金対象になります。
- Static Maps API
    - 10万回まで無料（ブラボー）
- Dynamic Maps
    - これが`Google Maps JavaScript API v3`で`new google.maps.Map()`を使用して地図を表示する場合です。`最大28,000回まで無料`で、`$7.00/1,000回`ごとに追加です。
    - ~~`<script src="https://maps.googleapis.com/maps/api/js?key=..."></script>`が**読み込まれる度に1カウント**です。~~
    - ~~(2018/07) 実験して確認しました。現在はscriptが読み込まれて、最初のmapインスタンスが生成されるときにカウントされます。公式FAQに書かれている通り、同じページ内で2個目のMapを作るときはカウントされません。~~
    - (2018/09) Google Maps API FAQから該当の説明が削除されていました。実験して確認したところ、現在は同じページ内で2個目のMapを作成するとカウントされます
- Static Street View
    - [Google Street View API](https://developers.google.com/maps/documentation/streetview/intro)です
    - 2万8,000回まで無料ですね
- Dynamic Street View
    - `Google Maps JavaScript API` v3の`StreetViewPanorama`
    - `Google Maps SDK for Android`の`StreetViewPanoramaView`
    - `Google Maps SDK for iOS`の`GMSPanoramaView`
    - ~~14,000回/pano となっているので、移動する度に 1pano としてカウントされます~~
    - (2018/09) FAQによるとインスタンスが作成されるごとに 1pano としてカウントされます


## Routes

![Screen Shot 2018-09-11 at 10.20.03 AM.png](https://qiita-image-store.s3.amazonaws.com/0/39529/bc8592ca-1823-4aeb-3bf2-92927531b0a4.png)

ルート検索は、Googleのコンピュータを使うから全体的に価格が高いですね。

## Places

![Screen Shot 2018-09-11 at 10.26.05 AM.png](https://qiita-image-store.s3.amazonaws.com/0/39529/7ab109b9-e815-bfcd-9011-2734dc03a885.png)

Google Places APIの料金体系はちょっと複雑です。

### Places Auto complete
Googleに確認したところ、
- `オートコンプリートリクエスト（文字単位）`となっているのは、[REST APIのPlace Autocomplete」(https://developers.google.com/places/web-service/autocomplete?hl=en)
- `オートコンプリートリクエスト（セッション単位）`となっているのが「Google Maps JavaScript API v3が提供するAutoComplete検索枠」

のようです。

「per session」の**session**は、検索枠をマウスでクリックしたときから、検索ボタンを押したときまでを1セッションとして定義している、とのことでした。

### Places Details
Google Places APIを使う場合、`オートコンプリート、テキスト検索、クエリ検索で条件に該当する場所を探し`、その中から選択した場所について「営業時間」「電話番号」など詳細な情報を取得する、という使い方をします。
それが[Places Details(プレイス詳細）](https://developers.google.com/maps/documentation/javascript/places?hl=ja#place_details)です。

このPlaces Detailsは取得したい情報を指定するフィールドによって、データ料金が発生します。

```js
var request = {
  placeId: 'ChIJN1t_tDeuEmsRUsoyG83frY4',
  fields: ['name', 'rating', 'formatted_phone_number', 'geometry'] <-- これ
};

service = new google.maps.places.PlacesService(map);
service.getDetails(request, callback);
```

- 基本データ
    - `address_component`, `adr_address`, `alt_id`, `formatted_address`, `geometry`, `icon`, `id`, `name`, `permanently_closed`, `photo`, `place_id`, `plus_code`, `scope`, `type`, `url`, `utc_offset`, `vicinity`
    - これらのフィールドを指定する場合は、`「プレイス詳細＋基本データ」`の行に該当します。
- 連絡先データ
    - `formatted_phone_number`, `international_phone_number`, `opening_hours`, `website`
    - これらのフィールドを指定する場合は、`「プレイス詳細＋基本データ＋連絡先データ」`の行に該当します。
- 雰囲気データ
    - `price_level`, `rating`, `review`
    - これらのフィールドを指定する場合は、`「プレイス詳細＋基本データ＋雰囲気データ」`の行に該当します。

料金表には書いてなかったのですが、ドキュメントページには次のような注意文が書いてあります。
![Screen Shot 2018-09-11 at 11.08.00 AM.png](https://qiita-image-store.s3.amazonaws.com/0/39529/674da266-10ab-22a9-8e44-0108a9a9469f.png)

> もしfieldsに何も指定しない場合、または省略した場合、全ての該当する可能性のあるフィールドが返され、それぞれ課金されます。これはPlaces Detailsリクエストに適用されます(Google Maps JavaScript API v3で提供される Place AutoComplete Widgetによるリクエストを含む)。

なんと!!　ちゃんと必要なフィールドだけを指定するようにしておきましょう。


### Find Places

- 条件に基づいて該当するPOIを検索してくれるAPIです
- fieldsの指定のルールはPlaces Detailsと同じです。
- もし該当するPOIがあるかどうかだけを調べるなら、「ID only」検索をすると良いでしょう。

### その他

- 表に書かれている通りです。



--------------

# $200を超えないようにするにはどうするか

- **「一箇所を表示するだけ」**の地図なら、[Google Maps Embed API](https://developers.google.com/maps/documentation/embed/guide)がお薦めです。なんていっても無料ですから。
<br><br>
- **「徒歩やルート情報も表示したい」**というなら、`Googleマップの埋め込み機能`がお薦めです。
<br><br>
- **「アイコンは変更したい。そこは譲れない」**というなら、「Google Static Maps API」を使用してとりあえず地図を表示して、本当に地図を拡大／縮小したい人だけGoogle Maps JavaScript API v3で地図を開くようなリンクを用意するといいです。
<br><br>
- **「アイコンは変更したい。そこは譲れない、でもプログラムから操作する必要がない」**というなら、[Googleマイマップ](https://www.google.com/mymaps/?hl=ja)がお薦めです。ブラウザ上で地図を簡単に作れて、`<iframe>`として埋め込むことができます。
<br><br>
- **「対象とするブラウザがAndroidまたはiOS」**なら、いっその事割り切って、全部Google Static Maps APIにしてしまいましょう。地図をクリックしたら、https://maps.google.com にリンクするようにすれば、Googleマップアプリがインストールされていれば開きますし、なければブラウザでGoogleマップが表示されます
<br><br>
- もし住所がわかっているなら、事前にGeocodingしておきましょう。プログラムで毎回行うのは、非効率です。
<br><br>
- ストリートビューも本当に表示する必要がありますか？再検討してみてください。
<br><br>
- **「いやいや、やっぱり全部使いたい。でも$200は超えたくない！」**という方は、`一日あたりの使用量`を設定することができます。
![Screen Shot 2018-09-11 at 11.54.16 AM.png](https://qiita-image-store.s3.amazonaws.com/0/39529/c453c44b-3599-aa47-8dc4-62e06c8aca0b.png)