RORK LABEN
ENGINE — Rork MaxはClaude CodeとClaude Opus 4.6を基盤に、ネイティブSwiftアプリを直接生成しますCORE ML — Rork MaxからCore MLの端末内推論・HealthKit・HomeKit・NFC・App Clipsといった機能に手が届きますSEED — Rorkは2026年4月にLeft Lane Capital主導で$15Mのシードを調達し、Peak XVやa16z Speedrunが参加しましたM&A — Rorkはアプリビルダー Paperline を買収し、エンジニアリング人材の獲得を目的に買収を継続する方針ですMARKET — Gartnerは2026年末までに新規アプリの75%がローコードまたはノーコードで作られると予測していますGROWTH — ノーコードAI市場は2024年の$4.9Bから2029年に$24.8Bへ、年38.2%の成長が見込まれていますENGINE — Rork MaxはClaude CodeとClaude Opus 4.6を基盤に、ネイティブSwiftアプリを直接生成しますCORE ML — Rork MaxからCore MLの端末内推論・HealthKit・HomeKit・NFC・App Clipsといった機能に手が届きますSEED — Rorkは2026年4月にLeft Lane Capital主導で$15Mのシードを調達し、Peak XVやa16z Speedrunが参加しましたM&A — Rorkはアプリビルダー Paperline を買収し、エンジニアリング人材の獲得を目的に買収を継続する方針ですMARKET — Gartnerは2026年末までに新規アプリの75%がローコードまたはノーコードで作られると予測していますGROWTH — ノーコードAI市場は2024年の$4.9Bから2029年に$24.8Bへ、年38.2%の成長が見込まれています
記事一覧/ビジネス
ビジネス/2026-06-16上級

Rork アプリの広告ROIを見えるようにする — SKAdNetwork コンバージョン値を収益に紐づける設計

Rork で作ったアプリに広告を打っても「どのキャンペーンが黒字なのか」が見えない最大の理由は、SKAdNetwork のコンバージョン値を収益と結びつけていないことです。6ビットの値設計を実装まで落とし込みます。

Rork498SKAdNetwork3ATT9広告運用Expo139アトリビューション2

プレミアム記事

ユーザー獲得広告を初めて回したとき、私が一番面食らったのは「インストールは増えているのに、どの出稿が黒字なのか一切分からない」という状態でした。iOS では ATT(App Tracking Transparency)の許可を取らない限り、広告クリックと個別ユーザーを結びつける IDFA が使えません。Google や AdMob のレポートには「インストール数」は出ても、「そのインストールが課金につながったか」が出てこないのです。

この穴を埋めるのが SKAdNetwork(SKAN)です。ただし SKAN が返してくるのは、ユーザー単位ではなく「キャンペーン × コンバージョン値」という匿名で集約された数字だけです。そして、そのコンバージョン値(0〜63 の整数)に何を意味させるかは、開発者である私たち自身が設計しなければなりません。ここを空欄のまま広告を回している個人開発者が、本当に多いと感じています。

私は壁紙・癒し系のアプリを App Store と Google Play で長く運用してきましたが、SKAN のコンバージョン値設計を入れる前と後では、広告予算の振り分け精度がまったく変わりました。ここではその設計を、Rork(Expo / React Native)で作ったアプリにそのまま組み込める形で残しておきます。

コンバージョン値は「6ビットの予算」だと考える

SKAN のコンバージョン値は 0 から 63、つまり 6 ビットしかありません。この狭い帯域に「アプリ内で起きた価値あるイベント」を詰め込む必要があります。よくある失敗は、思いつくイベントを全部別の値に割り当てて、64 種類すぐに使い切ってしまうことです。

私が採用しているのは、6 ビットを役割ごとに区切る方法です。

  • 上位2ビット(値 ×16): 収益ステージ(無課金 / 試用 / 初回課金 / 継続課金)
  • 中位2ビット(値 ×4): エンゲージメント深度(起動のみ / 主要機能到達 / 2日目復帰 / 通知許可)
  • 下位2ビット: 流入の質を測る補助フラグ

この区切りにすると、SKAN ダッシュボードに並ぶ数字を見ただけで「この出稿は試用までは来るが課金しない層を連れてくる」といった解釈ができるようになります。値そのものに意味の階層が埋め込まれているからです。

具体的なエンコード表は、運用するアプリの収益モデルに合わせます。サブスク型のアプリでは、私は次のような割り当てにしています。

// conversionValue.ts — 収益ステージを6ビットにエンコードする
export type RevenueStage =
  | "install"        // インストール直後
  | "activated"      // 主要機能に到達
  | "trial_started"  // 無料トライアル開始
  | "subscribed"     // 有料課金が確定
  | "retained_d2";   // 2日目に復帰
 
// 上位ビット = 収益ステージ(最重要シグナル)
const STAGE_BITS: Record<RevenueStage, number> = {
  install: 0b000000,        // 0
  activated: 0b000100,      // 4
  trial_started: 0b010000,  // 16
  subscribed: 0b110000,     // 48
  retained_d2: 0b001000,    // 8(activated と OR して使う)
};
 
// 課金額の概算レンジを下位ビットに添える(任意)
function revenueBucket(yen: number): number {
  if (yen >= 3000) return 0b11;
  if (yen >= 1000) return 0b10;
  if (yen > 0) return 0b01;
  return 0b00;
}
 
export function buildConversionValue(
  stage: RevenueStage,
  yen = 0,
): number {
  const cv = STAGE_BITS[stage] | revenueBucket(yen);
  // 0〜63 にクランプ(万一のビット溢れ対策)
  return Math.min(63, Math.max(0, cv));
}

ここで大切なのは、コンバージョン値は「上書きできるが、原則として上げる方向にしか更新できない」というルールがある点です。一度 48(課金)を送った後に 4(起動のみ)へ下げることはできません。ですから、最も収益価値の高いステージほど大きい数字を割り当てるのが鉄則になります。私は最初これを逆に設計してしまい、課金したユーザーの値が初日の起動イベントで上書きされて消える、という痛い目を見ました。

Expo アプリからネイティブの postback を呼ぶ

React Native / Expo には SKAN を直接叩く標準 API がありません。updatePostbackConversionValue(iOS 16.1 以降の SKAN 4.0 API)は Objective-C / Swift 側にあります。Rork が生成するのは JS 層のコードなので、ここはネイティブモジュールの薄い橋渡しを自分で足す必要があります。

Expo の Config Plugin と小さな Swift ファイルで実装できます。

// SkanModule.swift — SKAN 4.0 のコンバージョン値を更新する最小モジュール
import StoreKit
import ExpoModulesCore
 
public class SkanModule: Module {
  public func definition() -> ModuleDefinition {
    Name("Skan")
 
    AsyncFunction("updateConversionValue") {
      (value: Int, coarse: String, lockWindow: Bool, promise: Promise) in
      if #available(iOS 16.1, *) {
        let coarseValue: SKAdNetwork.CoarseConversionValue =
          coarse == "high" ? .high : coarse == "medium" ? .medium : .low
        SKAdNetwork.updatePostbackConversionValue(
          value,
          coarseValue: coarseValue,
          lockWindow: lockWindow
        ) { error in
          if let error = error {
            promise.reject("SKAN_ERR", error.localizedDescription)
          } else {
            promise.resolve(nil)
          }
        }
      } else {
        // iOS 16.0 以前は fine value のみの旧 API
        SKAdNetwork.updateConversionValue(value)
        promise.resolve(nil)
      }
    }
  }
}

JS 側からはこう呼びます。課金確定のタイミングで lockWindow: true を渡すと、計測ウィンドウを早めに確定させてポストバックを早く受け取れます。

import { requireNativeModule } from "expo-modules-core";
import { buildConversionValue } from "./conversionValue";
 
const Skan = requireNativeModule("Skan");
 
export async function reportSubscribed(yen: number) {
  const cv = buildConversionValue("subscribed", yen);
  // 課金は最終ステージなのでウィンドウをロックして即時集計に回す
  await Skan.updateConversionValue(cv, "high", true);
}
 
export async function reportActivated() {
  const cv = buildConversionValue("activated");
  await Skan.updateConversionValue(cv, "medium", false);
}

coarseValue(low / medium / high)は、インストール数が少なくて Apple のプライバシー閾値を超えられないキャンペーンでも返ってくる粗い指標です。個人開発の小規模な出稿では fine value(0〜63)がプライバシー保護で丸められて NULL になることが頻繁にあるので、coarse 側にも必ず意味を持たせておくのが実用上の保険になります。

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

この記事の続きを読む

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

この記事で得られること
0〜63 の6ビットに「収益が立つ瞬間」を割り当てる具体的なエンコード表
Expo アプリから updatePostbackConversionValue を呼ぶネイティブ橋渡しの実装
個人開発の運用で計測欠損を10%台に抑えるロック解除タイマーの調整値
Stripe による安全な決済 · いつでもキャンセル可能

この記事を購入する

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

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

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

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

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

関連記事

ビジネス2026-06-29
紹介コードで友達を招く仕組みを、重いバックエンドなしで設計する
Rork(Expo)アプリに紹介コードによる招待の仕組みを、専用サーバーを立てずに組み込みます。コード発行、遅延ディープリンクでの初回起動アトリビューション、二重付与を防ぐ冪等な報酬確定、自己紹介や端末重複への基本的な対策までを実装コード付きで扱います。
ビジネス2026-06-14
App Store のアプリ内イベントで休眠ユーザーを呼び戻す — Rork(Expo)アプリへのディープリンク実装
Rork(Expo)で作ったアプリの休眠ユーザーを App Store のアプリ内イベントで呼び戻す実装メモ。イベントカードの設計、ユニバーサルリンクのルーティング、効果計測までを個人開発の運用視点で解説します。
開発ツール2026-06-16
課金復元より先に広告を初期化したら、有料ユーザに一瞬広告が出た — Rork(Expo)アプリの起動順序設計
同意取得・ATT・広告初期化・課金復元・リモート設定を、起動の数百ミリ秒のあいだにどの順番で走らせるか。順序を1つ間違えるだけで、有料ユーザに広告が一瞬出たり、EEA で同意なしの計測が走ったりします。Rork で生成した Expo アプリの起動処理を1つのオーケストレータに畳み、競合を設計で潰す手順を実装メモとしてまとめます。
📚RECOMMENDED BOOKS
大規模言語モデル入門
山田育矢
LLM開発
生成AIプロンプトエンジニアリング入門
我妻幸長
プロンプト
Claude CodeによるAI駆動開発入門
平川知秀
AI駆動開発
※ アフィリエイトリンクを含みます
もっと見る →