◉RORK LABEN
●GPT-6.1 SOL — Rork のモデルメニューに追加(09-29)。Low/Medium/High を選べ、Pro・Max に含まれます●SONNET 5.5 — UI づくりが得意で、Sonnet 5 より出力が速いモデルが選べます(09-28)●SONNET 4.5 — Claude API での提供終了は 11/30、残り27日。API 連携を足したアプリは移行先の確認を●SDK 58 — React Native 0.88 に更新されました。Android のリリース版で R8 が既定オンになり、iOS は SceneDelegate を生成します●OBSERVE — EAS Observe がネイティブクラッシュも記録します(SDK 57.0.21 以降・10/07)●NEW — 起動広告が、背面から戻った回にしか出ていませんでした。「前面に戻った」合図が、…●GPT-6.1 SOL — Rork のモデルメニューに追加(09-29)。Low/Medium/High を選べ、Pro・Max に含まれます●SONNET 5.5 — UI づくりが得意で、Sonnet 5 より出力が速いモデルが選べます(09-28)●SONNET 4.5 — Claude API での提供終了は 11/30、残り27日。API 連携を足したアプリは移行先の確認を●SDK 58 — React Native 0.88 に更新されました。Android のリリース版で R8 が既定オンになり、iOS は SceneDelegate を生成します●OBSERVE — EAS Observe がネイティブクラッシュも記録します(SDK 57.0.21 以降・10/07)●NEW — 起動広告が、背面から戻った回にしか出ていませんでした。「前面に戻った」合図が、…
記事一覧/開発ツール
⬡ 開発ツール/2026-06-13中級

通知の許可は一度しか聞けない — Rork アプリにソフトアスク(事前確認)を実装して opt-in を底上げする

iOS の通知許可は一度拒否されると二度とダイアログを出せません。Rork(Expo)アプリで、起動直後に system prompt を撃つのではなく自前のソフトアスク画面を一枚挟み、価値が伝わった瞬間に許可を求める実装を expo-notifications で組みます。Android 13 の POST_NOTIFICATIONS、拒否後の設定誘導、opt-in 計測まで通します。

Rork611Expo234プッシュ通知20expo-notifications7オンボーディング10リテンション17

✦ プレミアム記事

運用しているアプリのプッシュ通知の opt-in 率を並べて眺めていたとき、ある 1 本だけが極端に低いことに気づきました。中身はほぼ同じ構成の壁紙アプリなのに、通知を許可してくれた人の割合が他の半分以下だったのです。

原因はすぐに分かりました。その 1 本だけ、起動して最初の画面が出るより前に通知の許可ダイアログを出していたのです。ユーザーから見れば「何のアプリかまだ分からないのに、いきなり通知を求められた」状態でした。

iOS の通知許可には、個人開発者が必ず一度はぶつかる残酷な仕様があります。UNUserNotificationCenter の許可ダイアログは、アプリの生涯で一度しか自動表示できません。ユーザーが一度「許可しない」を押すと、コードから何度 requestPermissions() を呼んでも、もうダイアログは出ません。残された道は「設定アプリを自分で開いてもらう」だけになります。

つまり通知の opt-in は「いつ・どう聞くか」で決まります。起動直後に system prompt を撃つのをやめ、自前のソフトアスク(事前確認)画面を一枚挟む設計を、Rork(Expo)アプリに実装していきます。私自身が複数のアプリ運用で効果を確かめた構成です。

なぜ「一度しか聞けない」が opt-in を左右するのか

iOS では通知許可は三つの状態を持ちます。notDetermined(まだ聞いていない)、authorized(許可済み)、denied(拒否済み)です。重要なのは notDetermined のときだけ system prompt が表示でき、それ以外では requestPermissions() が即座に現在の状態を返すだけで、何も表示されないという点です。

notDetermined は、アプリの生涯でたった一回のチャンスです。ここで雑に消費してしまうと、二度と取り戻せません。

一方ソフトアスクは、私たちが自由に何度でも出せる「自前の UI」です。ここで断られても iOS の状態は notDetermined のまま保たれます。だから「自前ダイアログで一旦聞いて、同意してくれた人にだけ system prompt を出す」という二段構えが成立します。system prompt の前に一段クッションを置くことで、貴重な一回を本気で許可してくれそうな人にだけ使えるのです。

私の手元の運用では、起動直後に system prompt を撃っていたアプリと、ソフトアスクを挟んで価値が伝わった後に聞くアプリとで、最終的な OS 許可率に 2 倍以上の差が出ていました。通知は再訪のきっかけそのものなので、この差はそのまま AdMob やサブスクの収益にも効いてきます。

全体の流れを先に決める

実装に入る前に、判断の順序を固めておきます。コードはこの順序をそのまま写したものになります。

  1. アプリ起動時に現在の許可状態を読む。authorized ならもう何もしない
  2. denied なら自前ダイアログは出さず、必要な場面で「設定で通知をオンにできます」という導線だけ出す
  3. notDetermined のときだけ、ソフトアスクを出す「きっかけ」が来たかを判定する
  4. きっかけが来たらソフトアスク画面を表示する
  5. ソフトアスクで「オンにする」が押されたら、初めて system prompt(requestPermissions())を撃つ
  6. 「あとで」が押されたら状態は触らず、次のきっかけまで待つ

この 6 ステップのうち、多くのアプリが 3 と 4 を飛ばして起動直後に 5 をやってしまっています。クッションを置く価値はここにあります。

✦

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

この記事の続きを読む

この先には、実装コードやベンチマーク結果など、実務でお役に立てる内容をご用意しています。このサイトは広告を掲載しておらず、サーバーや開発にかかる費用はメンバーの皆様のご支援で成り立っています。もしお役に立てていましたら、ご支援いただけますと大変ありがたいです。

この記事で得られること
✦起動直後に system prompt を撃つと iOS では一度の拒否で永久に再表示できなくなる仕組みを理解し、ソフトアスクで「自前ダイアログ → 同意した人だけに system prompt」という二段構えを expo-notifications で実装できるようになる
✦通知の価値が伝わった瞬間(保存・完了・3 回目の起動など)まで許可を遅延させる『きっかけ』判定を TypeScript の状態管理で組み、許可率を計測する 3 つのイベント(提示・同意・OS 許可)を設計できるようになる
✦拒否されたユーザーを Linking.openSettings() で設定アプリへ誘導する復帰導線と、Android 13 の POST_NOTIFICATIONS ランタイム権限の差分を、本番運用の落とし穴込みで実装できるようになる
Stripe による安全な決済 · いつでもキャンセル可能
✦

この記事を購入する

この先の内容をすべてお読みいただけます。一度のご購入で、いつでも何度でもアクセスできます。このサイトは広告を掲載しておらず、皆さまのご支援がサーバー費用などの運営を支えています。

または
メンバーシップなら全記事が読み放題 →
シェア

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

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

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

関連記事

⬡ 開発ツール2026-07-17
許可を聞かずに通知を届ける — Rork アプリの provisional 認可と、Expo の定番コードが握りつぶすもの
iOS には許可ダイアログを出さずに通知を配り始める provisional 認可があります。ところが Expo 公式が載せている定番の登録コードをそのまま使うと、provisional で通った端末が「拒否」として扱われ、避けたかったはずのダイアログが出ます。granted が false になる仕組みから、5値で許可状態を扱うフック、静かな配信を前提にした通知設計、昇格を求める判断、計測の分離までを実装込みで整理しました。
⬡ 開発ツール2026-10-30
開発ビルドでは動くのに、Release の iOS だけ起動直後に落ちる — scheme を外した app.json が原因の場合の確かめ方
expo-router のアプリで app.json に scheme がないと、Release の iOS だけ起動直後に落ちることがあります。Debug と Android が無事な理由、直し方の二択、scheme を外したい場合の考え方、提出前に見つける確認手順を書き残します。
⬡ 開発ツール2026-10-15
EXPO_PUBLIC_ の値が、開発では読めて本番だけ undefined になる書き方を、変換結果で見分けます
API の URL が開発中は読めるのに、ビルドした途端に undefined になる。原因は process.env の書き方でした。babel-preset-expo の変換結果を開発・本番で並べ、置き換わる書き方と残ってしまう書き方を表にしました。