GETパラメータに頼らない広告トラッキング 〜Symbolブロックチェーンを添えて〜

## はじめに
ポイントサイトで広告を利用して付与されるはずのポイントがつかず問合せして数ヶ月たってようやく付与された経験は無いでしょうか？私はあります。
ポイントが付与される条件（成果条件）がクレジットカードを作成するもので、付与予定のポイントがウン万円相当だったため、ウン万円がお預け状態でした。かなしい。

この悲しい事件はWeb広告にありがちなトラッキング漏れが原因でした。そこでこの悲劇を繰り返さないためにはどうしたらいいのか考えてみました。

Web広告のトラッキングでは、クリックとコンバージョン（成果）を正しく紐付けることが非常に重要です。しかし、よくある「GETパラメータでUUIDやad_idを渡す方式」には以下のような課題があります：

- リダイレクトやURL共有によってパラメータが欠落する  
- ユーザーが別ブラウザや端末でアクセスし直すと追えない  
- URLの改ざん・漏洩リスク  
- プライバシー保護（リファラ制限など）による影響  

これらを解決するために、**GETパラメータに依存しない「APIベース連携」方式**を採用し、**クリックや成果イベントをブロックチェーンに多段階で記録する分散ロガー方式**により、正確で検証可能なトラッキング基盤を構築する手法をSymbolブロックチェーンを利用する前提で考えてみます。


## APIベース連携とは

APIベース連携とは、ブラウザではなくサーバー同士（広告掲載サービス・ASP・広告主）がHTTP APIでUUIDやad_idをやり取りする方式です。


## ブロックチェーンで記録すべき理由

ブロックチェーンを使えば、次のような特性をトラッキング記録に付与できます。

| 特性 | 説明 |
|------|------|
| 🔒 耐改ざん性 | 一度書き込まれたトランザクションはネットワーク全体に保持され、変更が困難 |
| 🌍 分散性 | 単一障害点がなく、透明性が高い |
| 📜 透明性 | 誰でも履歴を見られ、トランザクションハッシュで時系列を追える |
| 🧾 永続性 | 経過年数にかかわらず消えることがない（アーカイブノードなどで復元可）


## なぜSymbolブロックチェーンなのか

広告トラッキングのようなユースケースにおいて、ブロックチェーンは「記録の改ざん防止」と「客観的な証明手段」として非常に有効です。

しかし、世の中には多数のパブリックブロックチェーンが存在する中で、本記事の設計では**Symbolブロックチェーン**を採用しました。


### 要件に照らしたブロックチェーン選定基準

| 要件 | 説明 |
|------|------|
| ✅ 改ざん困難な記録 | 誰が・いつ・何を記録したかを後から証明できること |
| ✅ 簡易な構造で開発可能 | 複雑なスマートコントラクトを書かずにデータ記録できること |
| ✅ 安価な手数料 | クリック／成果単位で頻繁に記録してもコストが現実的であること |
| ✅ 高可用性 | ノード停止や障害に強く、商用でも安定して使えること |
| ✅ 公開性とプライバシーのバランス | 透明性は保ちつつも、機密データの非開示が可能であること |


### Symbolの選定理由

✅ メッセージ付きのTransferTransactionを使えば、**わずか1トランザクションでJSONイベントを記録可能**
✅ 追加のスマートコントラクト開発が不要で、**TypeScriptやPHP等広く使われている開発言語でSDKを用いて記録可能**
✅ 改ざん困難で、後からExplorerやAPIで**誰でも検証可能**
✅ 日本国内でも採用実績が多く、技術文書・コミュニティによるサポートも充実
✅「記録のしやすさ」と「スケーラビリティの高さ」の両立が可能


Symbolはスマートコントラクトのような**複雑な実行環境を必要とせず**、シンプルなTransferTransactionのメッセージ機能だけで「いつ・誰が・何を記録したか」を残せるのが大きな強みとして挙げられます。

広告トラッキングのように：

- 簡単な構造で頻繁にデータを記録したい  
- 成果判定の根拠として後から検証できる状態にしたい  
- クリックや成果が改ざんされていないことを保証したい

といった要件には、**高機能なスマコンよりも軽量で可読性の高い記録方法が求められます。**
<details><summary><b>━━━━━━━━━━━━━━━━╮<br>┃&nbsp;&nbsp;&nbsp;&nbsp;TransferTransaction作成&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;┃<br>┃&nbsp;&nbsp;ソースコードを表示（折りたたみ）┃&nbsp;&nbsp;&nbsp;&nbsp;<br>╰━━━━━━━━━━━━━━━━╯</b></summary><div>

```typescript
const event = {
  adId: "AD-123",
  userHash: "abc123hashed",
  eventType: "click",
  timestamp: "2025-05-13T12:34:56Z"
};

const tx = TransferTransaction.create(
  Deadline.create(epochAdjustment),
  recipientAddress,
  [],
  PlainMessage.create(JSON.stringify(event)),
  NetworkType.TEST_NET
);
```
</div></details>


### Symbolは「技術者フレンドリー × ビジネス実用志向」

Ethereumのような高機能な汎用チェーンは確かに可能性は広いですが、本ユースケースのように「**頻度が高く、構造がシンプルで、記録証明性が重要**」な用途では、**Symbolのように必要十分かつ安価な台帳** が最適です。

スケーラビリティを考慮した際に下記の機能性も魅力的です。
<details><summary><b>━━━━━━━━━━━━━━━━━━━━╮<br>┃&nbsp;&nbsp;機能性についての説明を表示（折りたたみ）┃&nbsp;&nbsp;&nbsp;&nbsp;<br>╰━━━━━━━━━━━━━━━━━━━━╯</b></summary><div>

■堅牢性と柔軟性を実現
堅牢で拡張性に富むプラグイン型ブロックチェーンです。
一般的にブロックチェーンは、ブロックチェーン上のスマートコントラクトと呼ばれるトランザクションロジック(取引処理)を、自身で開発する必要があります。ブロックチェーン上の取引は取消ができないため、デプロイしたトランザクションロジックに不具合が生じた場合や脆弱性があった場合に、取り返しのつかない損失を被る可能性があり、開発者はシステム検証、デバッグに多大な時間をかけていました。Symbolは、トランザクションロジックがあらかじめ豊富にビルトインされているため拡張性に富み、それらは検証済みのためとても堅牢です。開発者は公開されているSDKやREST APIを介してこれらの高度なプラグイン型のトランザクションロジックを組み合わせ、利用することが容易に出来ます。

■ビルトイン
高度な取引機能が標準でビルトインされています。
特徴的な機能としてアグリゲートボンデッドというトランザクションタイプを有します。複数ウォレットの署名が必要な形式で、最大48時間以内に全員の署名が集まらなければ取引が確定しません。取引が確定されるまでは「パーシャル」と呼ぶ状態でブロックチェーン上にキャッシュされます。ビルトインで利用する事ができる為、簡単に既存のシステムへ高度なスマートコントラクトを実装する事ができます。

■簡単/便利
ノーコードでアセット・ネームスペースの発行が可能になっています。
Symbolではチェーン内の基軸通貨である「symbol:xym」とは別に、「モザイク」と呼ぶ独自のトークン（アセット）を開発者、または一般利用者が簡単に発行する事ができます。モザイクは通貨と同様にトランザクションを介して送受信する事ができ、例えば”独自通貨としての活用”や”証明書としての利用”等、ブロックチェーン上の取引を多次元に構成する事ができます。また、「ネームスペース」機能を別途利用可能で、Internetにおけるドメインのように、モザイクやアカウントに独自のラベルやメタデータを付与することもできます。
（引用：Symbol Community）

</div></details>

## 広告トラッキングにおけるAPIとブロックチェーンの役割

```mermaid
sequenceDiagram
    participant User
    participant 広告掲載サービス
    participant ASP
    participant 広告主
    participant ブロックチェーン

    User->>広告掲載サービス: 広告クリック
    広告掲載サービス->>ブロックチェーン: TransferTx(type:click, source:広告掲載サービス)
    広告掲載サービス->>ASP: API: click-notify(uuid)
    ASP->>ブロックチェーン: TransferTx(type:click, source:asp)
    ASP->>広告主: API: click-event(uuid)
    広告主->>ブロックチェーン: TransferTx(type:click, source:広告主)
    広告主->>User: サービス表示
    User->>広告主: 成果アクション
    広告主->>ASP: API: conversion-notify
    ASP->>ブロックチェーン: TransferTx(type:conversion, source:asp)
    ASP->>広告掲載サービス: API: conversion-event
    広告掲載サービス->>ブロックチェーン: TransferTx(type:conversion, source:広告掲載サービス)
```


## API通信とブロックチェーン記録の役割分担

ブロックチェーンだけですべてを完結させる構想は理論的には魅力的ですが、現実には以下の理由でAPI通信が不可欠です。

| 観点 | API通信 | ブロックチェーン |
|------|---------|------------------|
| 即時性 | ✅ 即通知・即レスポンス | ❌ ブロック確定に数秒～数十秒の遅延 |
| 通知／命令型通信 | ✅ リアルタイム指示・連携可能 | ❌ 投稿型でPullに依存（通知不可） |
| 秘匿性 | ✅ 認証付きHTTPSで秘匿可能 | ❌ すべてのデータが公開（対策要） |
| コスト | 無料（運用次第） | 手数料（トランザクション単位） |
| ロールバック耐性 | なし（アプリ依存） | ✅ 完全な記録・高い耐改ざん性 |

ブロックチェーンは**記録と証明**に最適であり、APIは**通信と同期**に必要です。  
両者を**役割に応じて併用するハイブリッド構成が適切**だと考えます。


### 特徴

- サーバー間通信で、GETパラメータ不要  
- 改ざんされにくく、再送やログ管理も可能  
- ブラウザの挙動や制限に影響されない  


## クリック通知API

広告掲載サービスでユーザーが広告をクリックしたタイミングで、UUIDと広告IDをAPI経由でASPに通知します。  
その後、ASPは同じ情報を広告主に中継します。

### 広告掲載サービス → ASP: `POST /api/click-notify`

```
POST /api/click-notify
Authorization: Bearer <service-api-token>
Content-Type: application/json

{
  "uuid": "abc-123",
  "ad_id": "AD-001",
  "timestamp": "2025-05-14T12:00:00Z"
}
```

処理意図：
- このリクエストにより、「このユーザーが広告をクリックした」ことをASPが正確に把握できます
- ブラウザに依存せずサーバーサイドで記録されるため、GETパラメータ欠落の問題を回避できます

### ASP → 広告主: `POST /api/click-event`

```
POST /api/click-event
Authorization: Bearer <asp-token>
Content-Type: application/json

{
  "uuid": "abc-123",
  "ad_id": "AD-001",
  "timestamp": "2025-05-14T12:00:01Z"
}
```

補足：
- 広告主側は、このUUIDをセッションやCookieなどで一時保持し、成果アクション時に照合します

- 広告主が直接ブロックチェーンへ記録する設計であれば、このAPIを省略し、UUID受信をトリガーとしてTransferTransactionを行っても構いません


## 成果通知API
### 広告主 → ASP → 広告掲載サービス
ユーザーが広告主のサービス上で成果条件を満たした場合、その情報は順にASP→広告掲載サービスへとAPIで通知されます。

### 広告主 → ASP: POST /api/conversion-notify
```
POST /api/conversion-notify
Authorization: Bearer <advertiser-api-token>
Content-Type: application/json

{
  "uuid": "abc-123",
  "ad_id": "AD-001",
  "conversion_id": "CV-20250514-999",
  "timestamp": "2025-05-14T12:34:56Z"
}
```
補足：
- 広告主は、UUIDに紐づくセッションを保持しており、成果条件を満たしたユーザーを正確に特定可能です

- この時点で、広告主がSymbolブロックチェーンに同一情報をTransferTransactionで記録することも推奨されます

### ASP → 広告掲載サービス: POST /api/conversion-event

```
POST /api/conversion-event
Authorization: Bearer <asp-api-token>
Content-Type: application/json

{
  "uuid": "abc-123",
  "ad_id": "AD-001",
  "conversion_id": "CV-20250514-999",
  "timestamp": "2025-05-14T12:35:00Z"
}
```
補足：
- 広告掲載サービスはこの通知を受け取り、成果を承認またはユーザーに還元処理を行います

- 同時に、UUID + adId + conversionId を含む成果ログをSymbolブロックチェーンに記録することで、記録の改ざん防止と証明が可能になります

## ブロックチェーンへの記録（即時分散記録）
下記のようなイベント内容の文字列のJSONでトランザクションを作成し、ネットワークにブロードキャストして広告掲載サービスが広告クリック時点で即時記録します。
```ts
const event = {
  uuid: "abc-123",
  adId: "AD-001",
  eventType: "click",
  source: "service",
  timestamp: new Date().toISOString()
};
```

（同様にASP、広告主でも記録）

## TransferTransactionベースでのイベント照合方法

Symbolブロックチェーンに記録された `TransferTransaction` は、任意のメッセージを含めることができ、**そのメッセージに記録したJSONを復元・解析することで照合が可能**です。

例えば、次のようなJSONが記録されていた場合：

```json
{
  "uuid": "a1b2c3d4-5678-9101-1121-3141abcde",
  "adId": "AD-2025-001",
  "eventType": "click",
  "userHash": "abc123hashed",
  "timestamp": "2025-05-13T12:00:00Z"
}
```
成果通知時に送られてきた adId と userHash の組み合わせが、ブロックチェーン上に存在するかどうかを確認できます。
<details><summary><b>━━━━━━━━━━━━━━━━━━━━╮<br>┃&nbsp;&nbsp;&nbsp;&nbsp;照合サンプルコードを表示（折りたたみ）┃&nbsp;&nbsp;&nbsp;&nbsp;<br>╰━━━━━━━━━━━━━━━━━━━━╯</b></summary><div>

```typescript
import {
  RepositoryFactoryHttp,
  TransferTransaction,
  TransactionGroup,
  TransactionSearchCriteria,
} from 'symbol-sdk';

const NODE_URL = 'https://sym-test-01.opening-line.jp:3001';
const factory = new RepositoryFactoryHttp(NODE_URL);
const transactionRepo = factory.createTransactionRepository();

// 受信アドレス（記録先）：広告掲載サービスのロガーアカウント
const recipientAddress = /* SymbolAddress.fromRawAddress("...") */;

const searchCriteria: TransactionSearchCriteria = {
  group: TransactionGroup.Confirmed,
  address: recipientAddress,
  pageSize: 100,
};

const { data: transactions } = await transactionRepo.search(searchCriteria).toPromise();

const expectedAdId = "AD-2025-001";
const expectedUserHash = "abc123hashed";

const matched = transactions
  .filter(tx => tx.type === 16724) // TransferTransaction
  .map(tx => (tx as TransferTransaction).message?.payload)
  .map(payload => {
    try {
      return JSON.parse(payload || '');
    } catch {
      return null;
    }
  })
  .find(event =>
    event &&
    event.adId === expectedAdId &&
    event.userHash === expectedUserHash
  );

if (matched) {
  console.log("クリックイベントがブロックチェーン上に存在します:", matched);
} else {
  console.log("一致する記録が見つかりませんでした");
}
```
</div></details>

## この仕組みのメリット

今回紹介した「GETパラメータを使わず、APIベースで連携し、Symbolブロックチェーンにトラッキングイベントを記録する方式」は、従来のWeb広告トラッキングと比較して多くの利点があります。

| 項目 | 内容 |
|------|------|
| 🔒 改ざん防止 | ブロックチェーンに記録されたイベントは誰にも改ざんできず、広告主・ASP・媒体社のいずれかが不正にデータを修正することを防げます。 |
| 🌐 GET不要 | UUIDなどをGETパラメータに含めずに済むため、リダイレクト中の欠落、改ざん、リファラ制限などを回避できます。 |
| ⚡ スケーラブル設計 | `TransferTransaction` を使えば記録件数に制限がなく、ノード依存ではあるもの非常に多くのトラッキングイベントを記録可能です。 |
| 🔁 再送・非同期対応 | APIベース連携により、リトライや非同期処理も可能で、信頼性の高い通信が構築できます。 |
| 🔍 第三者検証可能 | Symbolブロックチェーンはパブリックチェーンであり、記録されたトランザクションは第三者でも検証可能です（Explorer、SDK利用など）。 |
| 📦 柔軟な構成 | クリックログ、成果通知、証跡記録といった処理をサーバーサイドでモジュール化でき、システムの保守性・拡張性も高いです。 |
| 🔐 プライバシーに配慮 | ユーザーIDはハッシュ化して記録することで、個人情報を直接扱わずに安全に管理できます。 |


このように、APIベース連携とSymbolブロックチェーンを組み合わせることで、**より正確・透明性が高く・信頼できる広告トラッキングの仕組み**を実現することができます。

## まとめ

従来のGETパラメータを使った広告トラッキングは、利便性が高い反面、以下のような限界を抱えています：

- ブラウザやリダイレクト経路によるパラメータ欠落
- 改ざんやなりすましのリスク
- ブラウザのプライバシー保護機能（ITPなど）によるトラッキング阻害
- 記録の信頼性・検証性の不在

これらの問題に対し、今回紹介した「APIベース連携 × Symbolブロックチェーン × TransferTransaction記録」のアプローチは、次のような特徴を持ちます：

- GETパラメータを排除し、安全かつ確実にUUIDやad_idを伝達
- 成果発生までのクリック記録をオフチェーンとオンチェーンで照合可能に
- Symbolブロックチェーンを活用して、記録内容の改ざんを防止
- 第三者でも確認できる、検証可能なログを残せる
- スマートコントラクト不要で、Node.jsなどから簡単に実装可能

この仕組みにより、**「トラッキング漏れ」や「成果の証明ができない」などの問題を根本から解決**しつつ、広告主・ASP・媒体社すべてにとってフェアで信頼性のあるトラッキングが実現できます。


実用化に向けては、以下のような段階的導入も可能です：

1. **PoC（概念検証）**：自社内でUUID通知 → ブロックチェーン記録までを小規模に試す  
2. **API仕様の共有**：ASPや広告主とトラッキングAPIの仕様を取り決める  
3. **オフチェーンDBとの照合連携**：成果通知時の自動照合ロジックを実装  
4. **オンチェーンログの監査対応**：トランザクションハッシュを使って監査証跡として活用

トラッキングの透明性と証明可能性を高めたいと考えている方には、ぜひ一度Symbolでの実装を試していただきたいと思います。

## 関連リンク
- [速習Symbol](https://learn.ja.symbol-community.com/)
- [Symbol SDK for TypeScript](https://github.com/symbol/symbol-sdk-typescript-javascript)
- [Symbol開発者ドキュメント](https://docs.symbol.dev/)
- [Symbol Community](https://symbol-community.com/ja)
- [ブロックチェーンでトランザクションを送信してみた](https://qiita.com/teriteria/items/c2f5596782a7742f264e)
- [「Why Blockchain?」という問いに対する私の考え](https://qiita.com/salaryman-toushi/items/0640a7231d70d502a236)