GEMINI LABEN
NANOLITE — Nano Banana 2 Liteが登場しました。Googleで最も速く、最もコスト効率の高いGemini Imageモデルで、軽量な画像生成を安く回したい用途に向いていますOMNIFLASH — Gemini Omni Flashがpublic previewになりました。ネイティブにマルチモーダルなモデルで、企業や開発者が独自の動的な動画ワークフローを構築できますAGENTS — Managed Agentsが拡張されました。background: trueでサーバー側の非同期実行とポーリング、リモートMCPサーバー連携、対話をまたぐ認証情報のリフレッシュに対応しますMEMORY — Memory BankのIngestEvents APIが一般提供になりました。イベントの取り込みとメモリ生成を分離し、コンテンツを継続的にストリームできますTHROUGHPUT — Provisioned Throughputで、同一モデル・同一リージョンに対して最大7件の保留オーダーを提出できるようになりましたDEPRECATE — 画像生成モデルは8月17日に、Gemini Enterprise Agent PlatformのGrok 4.1系は8月20日に停止される予定ですNANOLITE — Nano Banana 2 Liteが登場しました。Googleで最も速く、最もコスト効率の高いGemini Imageモデルで、軽量な画像生成を安く回したい用途に向いていますOMNIFLASH — Gemini Omni Flashがpublic previewになりました。ネイティブにマルチモーダルなモデルで、企業や開発者が独自の動的な動画ワークフローを構築できますAGENTS — Managed Agentsが拡張されました。background: trueでサーバー側の非同期実行とポーリング、リモートMCPサーバー連携、対話をまたぐ認証情報のリフレッシュに対応しますMEMORY — Memory BankのIngestEvents APIが一般提供になりました。イベントの取り込みとメモリ生成を分離し、コンテンツを継続的にストリームできますTHROUGHPUT — Provisioned Throughputで、同一モデル・同一リージョンに対して最大7件の保留オーダーを提出できるようになりましたDEPRECATE — 画像生成モデルは8月17日に、Gemini Enterprise Agent PlatformのGrok 4.1系は8月20日に停止される予定です
記事一覧/API / SDK
API / SDK/2026-05-30中級

Gemini 2.5 Flash で App Store Connect の日次売上をSlack要約に変えて2ヶ月運用した所感

App Store Connect の Sales/Trends API から落とした日次レポートを、Gemini 2.5 Flash で短いSlack要約に変える運用を2ヶ月続けた所感をまとめます。Pro との使い分け、AdMob 収益と並べて読むときの工夫、要約が滑った日の対処を運用ログから残します。

gemini-api279gemini-flash6app-store-connect2indie-dev21ios12slack3

App Store Connect の数字を、毎朝Slackで「使える短い文章」として読みたい。2014年から続けている個人開発の現場で長らく感じていた小さな願いを、Gemini 2.5 Flash でようやく形にした2ヶ月のメモです。

毎朝のSlackに数字ではなく所感を流したかった理由

iOS と Android で累計5,000万ダウンロードに育った壁紙系と癒し系のアプリ群を、ひとりで運営しています。AdMob 収益が柱ですが、有料アプリと App内課金の売上も無視できない規模で動いており、地域別の崩れ方や OS バージョン別の傾向は毎日眺めたい類の情報です。

それまでは App Store Connect の Sales/Trends API から落とした CSV を Numbers で開いて、自分の頭の中で「昨日と比べてどう動いたか」を整理していました。数字を読むのは嫌いではないのですが、寝起きの15分をそこに溶かしてしまうのが惜しく、もう少し短い時間で全体像を掴みたかったのです。

そこで Gemini 2.5 Flash を要約レイヤーに挟み、Slack の朝チャンネルに「数字+一段落の所感」が並ぶ形にしました。本記事はその仕組みを2ヶ月運用したあとの率直な振り返りです。

パイプラインの全体像

ジョブは Cloudflare Workers Cron で毎日 JST 7:30 に起動し、以下の順に処理しています。

# scripts/daily_revenue_digest.py(抜粋)
import os, json, datetime
from google import genai
from appstoreconnect_client import fetch_sales_report
from slack_sdk import WebClient
 
YESTERDAY = datetime.date.today() - datetime.timedelta(days=1)
WINDOW = 14  # 14日分の傾向を一緒に渡す
 
def build_prompt(today_rows, trend_rows):
    return f"""
あなたは個人開発者の運用パートナーです。
以下は iOS / Android アプリ群の昨日({YESTERDAY})の売上ログと、直近{WINDOW}日のトレンドです。
3段落以内、各150字以内で、日本語の所感を書いてください。
ルール:
- 数値は最大3つまで本文に入れる
- 異常検知は「平常」「やや異常」「要確認」の3段階で1行ラベルを付ける
- 翌朝に読む人が安心できるトーンで、扇情語は使わない
 
[昨日の生データ]
{json.dumps(today_rows, ensure_ascii=False)}
 
[直近{WINDOW}日のトレンド]
{json.dumps(trend_rows, ensure_ascii=False)}
"""
 
client = genai.Client(api_key=os.environ["GEMINI_API_KEY"])
resp = client.models.generate_content(
    model="gemini-2.5-flash",
    contents=build_prompt(today_rows, trend_rows),
    config={"temperature": 0.3, "max_output_tokens": 600},
)
WebClient(token=os.environ["SLACK_BOT_TOKEN"]).chat_postMessage(
    channel="#dolice-morning",
    text=resp.text,
)

要点はプロンプトに2つだけルールを書いたことです。1つは「数値は本文に最大3つまで」、もう1つは「扇情語を使わない」です。前者は要約が数字の羅列に逆戻りするのを防ぎ、後者は2.5 Flash が時折出す「劇的に伸びました」「驚異の上昇」といった、個人開発者の朝に欲しくないテンションを抑えるためでした。

Pro ではなく Flash を選んだ理由

最初のひと月は Gemini 2.5 Pro で試しました。文章は自然でしたが、150字 × 3段落というサイズに対しては明らかに過剰で、月の API コストが概算で4倍弱になりました。

App Store Connect の日次売上は構造化されたタブlular データで、しかも前日比という比較対象が明確です。Flash でも「14日のトレンドのうち、今日が下振れたら指摘して」程度の判断は十分に下せました。temperature: 0.3 を維持する限り、暴走するような所感は2ヶ月で1度も出ていません。

Pro を残しているのは週次のロールアップだけです。月曜の朝に1回、過去7日の Sales/Trends と AdMob レポートを並べ、「週として何が伸びたか」「来週注視するべき地域はどこか」を200字程度の所感にまとめてもらっています。深い因果関係を考えてほしいときだけ Pro、淡々と読みたいときは Flash、という切り分けがいまのところ落ち着いています。

14日のトレンドを「一緒に渡す」だけで読み違いが減った

最初の数週間は、Flash に「昨日の売上だけ」を渡していました。要約自体は数行できれいに上がってくるのですが、「平常」「やや異常」の判断が日によって揺れる弱点がありました。Flash の側で何が平常なのかを知らないので、当たり前と言えば当たり前です。

そこで、Sales/Trends API から取得した直近14日分のレコードを、軽く集約した状態で一緒に渡すように変えました。地域別の DL 数だけ、課金タイプ別の売上だけ、というふうにスリムに切ってから JSON で添える形です。

def slim_trend(rows, days=14):
    by_country = {}
    for r in rows:
        key = r["country"]
        by_country.setdefault(key, []).append(r["amount_jpy"])
    return [
        {"country": k, "avg": round(sum(v)/len(v)), "n": len(v)}
        for k, v in by_country.items()
    ]

平均値とサンプル数だけ添えるだけで、Flash の所感は明らかに落ち着きました。「直近14日でドイツが平均1,820円のところ、今日は2,140円」という比較が自然に書かれるようになり、私が頭の中でやっていた前日比の暗算がほぼ要らなくなりました。トークンコストは2割増えましたが、要約の信頼性が上がった対価としては十分に安いものでした。

AdMob と一緒に読むとき詰まったこと

App Store Connect 単体での要約は早い段階で安定したのですが、AdMob レポートと並べた瞬間に Flash が混乱した時期がありました。原因はシンプルで、AdMob の eCPM は USD 建て、App Store Connect の売上はストアごとに通貨が違うため、同じ表の中で「+18%」と「+22円」が混在し、Flash の所感が単位の混同を起こしていました。

対処は、プロンプトに与える前に Python 側で全額を JPY 換算に揃え、必要なら currency_original という別フィールドで原通貨を残す、という前処理を入れただけです。

def normalize_revenue(rows, fx_table):
    out = []
    for r in rows:
        jpy = r["amount"] * fx_table.get(r["currency"], 1.0)
        out.append({
            "country": r["country"],
            "amount_jpy": round(jpy),
            "currency_original": r["currency"],
        })
    return out

LLM 側の限界を技術で取りに行くより、データ側で素直に整える方が運用ログ的にも安全でした。LLM に通貨換算の判断まで任せると、為替が動いた日に「異常に伸びた」と誤認識される事故が起こりやすかったのです。

滑った日の対処と「平常ラベル」の効用

2ヶ月のうち、Flash の要約が滑った日は3回ありました。いずれも App Store Connect 側の遅延配信で「昨日のデータが半日分しか入っていない」状況で、それを Flash が「売上が急減した」と読み違えてしまった日でした。

直したのは2点です。

1つ目は、Sales/Trends API から取得したレコードに「対象期間の終了タイムスタンプ」を必ず添え、Flash 側にも「データの確報性: 速報 / 確報」というメタ情報を渡すようにしたこと。2つ目は、所感の冒頭に「平常 / やや異常 / 要確認」の1行ラベルを必ず付ける運用にしたことです。

def annotate_completeness(rows):
    return [
        {**r, "data_state": "preliminary" if r["row_count"] < r["expected"] * 0.9 else "final"}
        for r in rows
    ]

ラベルが付くことで、寝起きの15秒で「これは普通の日」と判断できるようになり、3段落の所感を読むかどうかも自分で選べるようになりました。要約があることよりも、要約に手を出さないでよい朝を増やすことが、運用品質の体感を変えました。

2ヶ月運用してわかった、所感の限界と相棒としての距離感

Flash の要約は、個人開発の朝チャンネルにちょうど良い相棒になりました。一方で、Flash の所感はあくまで「数字をなだらかに読ませる補助線」であって、戦略を立てる材料には足りません。たとえば「ドイツ語圏で壁紙アプリの新規DLが2週間連続で増えている」という事実は拾えても、「そこに合わせて新作カラーパレットを足すべきか」までは判断できません。

その境界を引いたあとは、毎朝のSlackは「読んで安心するための場所」、週次の Pro レポートは「考えるための場所」、と役割を分けるようになりました。1997年に16歳でインターネットに触れて以来、独学のプログラミングが個人運営の支えになってきましたが、その手触りに「数字をやわらかく読む層」が一つ加わったような感覚です。

明日の朝、もし同じパイプラインを試してみたい方がいたら、まずは Cloudflare Workers Cron と Gemini 2.5 Flash の組み合わせで「Slack に150字の所感を流す」だけのミニマム構成から始めてみるのが良いと思います。プロンプトに「扇情語を使わない」の一文を必ず添えること、それだけで朝の質感がだいぶ変わるはずです。

お読みいただきありがとうございました。

シェア

お読みいただきありがとうございます

Gemini Lab は広告なしで運営しており、サーバー費用などの運営コストはメンバーシップのご支援で賄っています。実装コード・ベンチマーク・本番設計パターンなど、実務でお役立ていただける記事を毎日更新しています。もし読んでよかったと感じていただけましたら、ぜひご覧ください。

  • コピー&ペーストで使える実装コード付き
  • 毎日新しい上級ガイドを追加
  • ¥580/月 または ¥1,480 の永久アクセス
メンバーシップを見る →

もしこの記事がお役に立ちましたら、チップ(¥150)で応援いただけると大変励みになります。広告なしでの運営を続けるため、皆さまのご支援が大きな力になっています。

関連記事

API / SDK2026-05-31
Gemini 2.5 Flash で App Store のキーワード欄を多言語最適化した1ヶ月の所感
App Store Connect の100文字キーワード欄を、40本の壁紙アプリ×複数ロケールで Gemini 2.5 Flash に下書きさせた1ヶ月の運用ログです。CJK のバイト数問題、タイトル重複の排除、禁止語の落とし穴まで、現場でつまずいた点を淡々と記録します。
API / SDK2026-05-25
Gemini 2.5 Flash で個人開発アプリのヘルプ翻訳を3ヶ月運用した所感
iOS / Android の個人開発アプリで提供してきた多言語ヘルプを、Gemini 2.5 Flash を中心とした翻訳パイプラインで運用し始めて3ヶ月が経ちました。Pro との使い分け、訳文ドリフトへの備え、AdMob 収益に与えた小さな効果まで、運用ログに残った所感を淡々と記録します。
API / SDK2026-06-23
Gemini 3.2 Pro の Function Calling を iOS/Android アプリに統合する実装パターン
Gemini 3.2 Pro の Function Calling を iOS/Android アプリに統合する実装ガイド。SwiftUI・Kotlin 両対応の動くコード例と、個人開発の壁紙アプリで実証した本番設計パターン(コスト・レイテンシ・段階ロールアウト・回帰テスト)を解説します。
📚RECOMMENDED BOOKS
大規模言語モデル入門
山田育矢
LLM開発
生成AIプロンプトエンジニアリング入門
我妻幸長
プロンプト
Claude CodeによるAI駆動開発入門
平川知秀
AI駆動開発
※ アフィリエイトリンクを含みます
もっと見る →