ある朝、App Store Connect を開いたら、5年運用している壁紙アプリの英語版スクリーンショットだけが、半年前の古い UI のままになっていることに気づきました。日本語版だけは新しい iOS 26 のデザインに差し替えていたのですが、英語版に手が回らないまま、いつの間にかリリースから 4 バージョン進んでしまっていたのです。Apple Search Ads でその英語版に出稿していたので、CTR が前月比で 18% ほど落ちているのも当然でした。
これは個人開発で複数のアプリを並行運用するときに、ほぼ確実に起きるドリフトだと思います。私自身、2014年からアプリ事業を続けて累計 5,000万 DL ほどになりますが、ローカライズしたスクリーンショットの維持は昔からいちばん後回しになりがちでした。Antigravity の Background Agent を運用監視に使い始めた流れで、ついでに App Store スクリーンショットの多言語更新も任せてみよう、と決めてから 5 週間。今回の記事は、その間に何を任せて、何を任せなかったかの所感です。
なぜ「Background Agent に丸ごと」ではなく「下処理だけ」にしたか
宮大工をしていた両祖父の影響で、私には「最後の仕上げは人間が手でやるもの」という感覚があります。最初の週に、つい欲が出て「スクリーンショットの選定から多言語化、Connect への差し替えまで全部任せる」というジョブを書いたのですが、これは早々にやめました。理由は単純で、デザインの判断(どのカットを 1 枚目にするか、コピーの語感を英語と中国語でどこまで揃えるか)は、まだエージェントに丸投げできる成熟度ではないと感じたためです。
5 週間運用してみて落ち着いた境界線は、こうなりました。
- 下処理(端末別の解像度書き出し、テキスト差し込みのレイヤー位置調整、各言語の文字数オーバー検出)は Background Agent
- 1 枚目のキービジュアル選定、コピーの語感、最終承認は人間
この役割分担にしてから、私が触る時間は週末の 90 分くらいに圧縮できました。
動かしているジョブの骨格
Background Agent に渡している定義は、概ね次の形に落ち着いています。説明のため要点だけ抜き出していますが、実物もこれに近い構成です。
# antigravity/agents/appstore-screenshots-weekly.yaml
name: appstore-screenshots-weekly
schedule: "0 4 * * SUN" # 日曜 04:00 JST
inputs:
apps:
- { bundle_id: jp.dolice.wallpaper.zen, locales: [ja, en, zh-Hans, zh-Hant, ko, es-MX, fr, de] }
- { bundle_id: jp.dolice.wallpaper.dark, locales: [ja, en, zh-Hans, zh-Hant, ko, es-MX, fr, de] }
- { bundle_id: jp.dolice.wallpaper.mind, locales: [ja, en, zh-Hans, zh-Hant, ko] }
- { bundle_id: jp.dolice.wallpaper.kid, locales: [ja, en, zh-Hans, ko] }
tools:
- fs.read_master_psd
- text.translate # 私が用意した用語集を参照
- image.render_screenshot # 端末枠込みで PNG 書き出し
- asc.list_localizations
- notify.slack
steps:
- id: detect_master_diff
run: fs.read_master_psd($app.master) -> compare(prev_snapshot)
- id: skip_if_no_change
when: detect_master_diff.changed == false
run: notify.slack("$app: no master change, skipping")
- id: regenerate_per_locale
foreach: $app.locales
run: |
text.translate(source=$app.master.copy, target=$locale, glossary=$app.glossary)
-> image.render_screenshot(device=[iPhone-6.9, iPhone-6.5, iPad-13])
- id: report
run: notify.slack(diff_summary + warnings)要は「マスター PSD が変わった週だけ動く」「最終的に Connect へ流すかは Slack でレビューしてから人間が判断する」という構成です。asc.list_localizations だけは差し替え前のロケール一覧を取得するために置いていて、書き戻し(asc.upload_screenshot)は外してあります。書き戻しを自動化しなかった理由は次の章に書きます。
自動アップロードを外した3つの理由
最初の週は書き戻しまで自動化していました。しかし第 2 週で、英語のキャッチコピーの語尾が中途半端なまま反映され、レビュー前のメタデータ画面で気づくという小さな事故が起きました。そこから書き戻しを止めて、次の 3 つを理由として整理しました。
- 語感は最終的に人間の責任が残る領域。1997年に独学でプログラミングを始めて以来、技術には開いているつもりですが、文字の語感まで丸投げしてよい段階ではまだないと感じています
- Connect への書き戻しは取り消しのコストが高い。スクリーンショットを上書きしたあとで前のバージョンに戻すには手動アップロードが必要で、夜間ジョブの失敗を朝に直すには重い作業になる
- Apple Search Ads とのタイミング調整。新しいスクリーンショットに切り替えるタイミングで、対応するキーワード入札も微調整したいときがあり、両方を人間がレビューしながら 1 セットで切り替えるほうがアトリビューションが追いやすい
5週間でぶつかった具体的な壁
数字を 3 つだけ書いておきます。アプリ 4 本 × ロケール最大 8 = 32 セットを 5 週間で 5 回まわしました。延べ 160 セットの生成のうち、そのまま採用できたのは 121 セットで、人間の手直しが入ったのが 39 セットです。手直しの内訳はおおむね次の比率でした。
- 中国語簡体・繁体の文字数オーバー(縦長デバイスで折り返しが汚くなる)が 18 件
- 韓国語のフォント高さがズレてキービジュアルにかぶった事故が 9 件
- スペイン語の語尾調整(メキシコ向け / スペイン向けの口語差を吸収しきれない)が 8 件
- 日本語マスターの行間調整がレンダラに反映されなかったケースが 4 件
「中国語の文字数オーバー」は事前にバリデーションを足せばエージェント側で吸収できる類のものでしたので、第 3 週でステップを 1 つ追加しました。一方、「韓国語フォントのベースラインずれ」は端末別のレンダリングエンジンに依存する話で、結局は手で確かめるルールにしました。Background Agent を回す前から私の中で漠然と感じていた境界線が、5 週間で具体的に言語化できた感覚があります。
レポーティングを Slack に絞ったことの効用
notify.slack 1 つに絞ったのは、複数の通知先を持つと「あとで見る」が積み上がるのを学んでいたためです。離れて暮らす子どもたちが寝静まったあと、夜の Slack だけ確認すれば終わる、という運用を保ちたかったのが本音です。Background Agent には「やったことを長文で書かない、変更があった項目だけ箇条書きで送る」という指示を入れています。差分が空のときは「変更なし」とだけ送ります。
レポートのフォーマットも何回か直しました。最終的に落ち着いたのは、こういう形です。
[Sun 04:18 JST] appstore-screenshots-weekly
- zen: ja=OK en=⚠️ コピー語尾 zh-Hans=⚠️ 字数 zh-Hant=OK ko=OK es-MX=OK fr=OK de=OK
- dark: ja=OK en=OK zh-Hans=OK zh-Hant=OK ko=⚠️ フォント高 es-MX=OK fr=OK de=OK
- mind: no master change, skipped
- kid: ja=OK en=OK zh-Hans=OK ko=OK
to_review_in_drive: 5 PNGsここから Google Drive のレビュー用フォルダを開いて、気になるものだけ私が直す、という形に落ち着きました。
5週間を経ての結論
このジョブは「Background Agent が個人開発のどこを置き換えるか」を考える上で、私にとっては良い実験でした。書き戻し(書く)まで自動化した第 1 週は速かったのですが事故が増え、書き戻しを外した第 2 週以降は時間を 90 分まで圧縮しつつ事故が消えました。便利だから全部任せるのではなく、責任が残る境界線を明確にする工程を一度通したことが、いちばんの収穫でした。
私自身、2019年に吉祥寺の駅上で見た光の輪をきっかけに視覚表現の比率が上がりました。それ以来、自分のアプリのスクリーンショットも作品の延長として扱う気持ちで作っています。最後の語感や 1 枚目の判断を人間に残しておくのは、その時間を確保するためのレーンを引きたかった、というのも背景にあります。
次に手をつけたいのは、Apple Search Ads のキーワード入札と、スクリーンショット差し替えのタイミングを 1 つの差分ビューにまとめる仕組みです。同じ題材で運用が進んだら、また所感を書こうと思います。
お読みいただきありがとうございました。同じような運用境界で悩んでいる個人開発の方の参考になれば嬉しいです。