Shopify メタフィールド設計:PII完全分離アーキテクチャ
🎯 設計方針
基本原則
const designPrinciples = {
piiSeparation: "個人情報はShopifyに完全集約、D1は非PIIのみ",
singleSource: "Shopifyを単一真実源、D1はキャッシュ・処理状態",
brandSeparation: "メタフィールドでブランド完全分離",
photoIntegration: "R2写真ファイルとShopify注文の完全連携",
// ビジネス要件
multiStore: "1 Shopifyアカウント、3ブランドストア運用",
photoDisplay: "マイページで購入した写真の完全表示",
orderHistory: "ブランド横断・ブランド別注文履歴",
printSpec: "89mm正方形高品質プリント仕様管理"
}
🏪 メタフィールド構造設計
1. Product Level メタフィールド
// 商品レベル:ブランド・仕様管理
interface ProductMetafields {
// ブランド管理
brand: {
namespace: "nekomata",
key: "brand_id",
type: "single_line_text_field",
value: "neko" | "tokinoe" | "dog"
},
brand_display: {
namespace: "nekomata",
key: "brand_display_name",
type: "single_line_text_field",
value: "Nekomata" | "TOKINOE" | "Dog"
},
// プリント仕様
print_size: {
namespace: "nekomata",
key: "print_dimensions",
type: "json",
value: {
width: 89,
height: 89,
unit: "mm",
format: "square"
}
},
print_quality: {
namespace: "nekomata",
key: "print_specification",
type: "json",
value: {
dpi: 300,
colorSpace: "sRGB",
paperType: "premium_matte",
coating: "UV_resistant"
}
},
// 商品分類
category: {
namespace: "nekomata",
key: "product_category",
type: "single_line_text_field",
value: "photo_print" | "album" | "frame"
},
// 配送設定
shipping_profile: {
namespace: "nekomata",
key: "shipping_config",
type: "json",
value: {
lead_time_days: 3,
shipping_class: "photo_print",
international: false
}
}
}
2. Order Level メタフィールド
// 注文レベル:ブランド・処理状態管理
interface OrderMetafields {
// ブランド識別
brand_order: {
namespace: "nekomata",
key: "brand_context",
type: "json",
value: {
brand: "neko" | "tokinoe" | "dog",
store_name: string,
domain: string,
theme: "premium" | "simple" | "family"
}
},
// 注文処理状態
processing_state: {
namespace: "nekomata",
key: "order_processing",
type: "json",
value: {
status: "uploaded" | "processing" | "printed" | "shipped" | "delivered",
bff_order_id: string, // D1で管理する処理ID
worker_session: string, // Workers処理セッション
last_updated: string, // ISO timestamp
processing_time: number // 処理時間(ms)
}
},
// 品質管理
quality_check: {
namespace: "nekomata",
key: "quality_control",
type: "json",
value: {
image_validation: boolean,
print_preview_generated: boolean,
color_correction_applied: boolean,
manual_review_required: boolean
}
},
// 配送追跡
fulfillment_tracking: {
namespace: "nekomata",
key: "delivery_tracking",
type: "json",
value: {
tracking_number?: string,
carrier: string,
estimated_delivery: string,
delivery_confirmation?: string
}
}
}
3. LineItem Level メタフィールド(重要)
// ラインアイテムレベル:写真ファイル完全管理
interface LineItemMetafields {
// 📸 写真ファイル情報(最重要)
photo_file: {
namespace: "nekomata",
key: "uploaded_photo",
type: "json",
value: {
r2_url: string, // R2での永続URL
r2_key: string, // R2オブジェクトキー
original_filename: string, // アップロード時ファイル名
file_hash: string, // ファイル整合性検証用
upload_timestamp: string, // アップロード日時
file_size: number, // ファイルサイズ(bytes)
image_dimensions: { // 画像サイズ
width: number,
height: number
}
}
},
// プリント詳細仕様
print_details: {
namespace: "nekomata",
key: "print_specification",
type: "json",
value: {
quantity: number, // プリント枚数
finish: "matte" | "glossy" | "premium",
border: boolean, // 白枠の有無
color_correction: "auto" | "manual" | "none",
crop_settings?: { // トリミング設定
x: number,
y: number,
width: number,
height: number
}
}
},
// 💰 価格詳細
pricing_breakdown: {
namespace: "nekomata",
key: "item_pricing",
type: "json",
value: {
base_price: number, // 基本価格
quantity_discount: number, // 数量割引
premium_finish_fee: number, // プレミアム仕上げ追加料金
rush_fee: number, // 特急料金
total_item_price: number // アイテム合計
}
},
// 🎨 画像処理情報
image_processing: {
namespace: "nekomata",
key: "processing_metadata",
type: "json",
value: {
ai_enhancement_applied: boolean,
color_profile_conversion: boolean,
resolution_upscaling: boolean,
noise_reduction: boolean,
print_ready_url: string, // 印刷用最終画像URL
processing_log: string[] // 処理ログ
}
}
}
4. Customer Level メタフィールド
// 顧客レベル:ブランド横断管理
interface CustomerMetafields {
// 🔥 Firebase統合
firebase_integration: {
namespace: "nekomata",
key: "firebase_uid",
type: "single_line_text_field",
value: string // Firebase UID(統合認証キー)
},
// 📊 ブランド利用履歴
brand_activity: {
namespace: "nekomata",
key: "multi_brand_usage",
type: "json",
value: {
neko: {
first_order: string, // 初回注文日
total_orders: number, // 総注文数
total_spent: number, // 総購入額
last_order: string, // 最終注文日
favorite_finish: string // よく使う仕上げ
},
tokinoe: {
// 同様の構造
},
dog: {
// 同様の構造(将来用)
}
}
},
// 🎯 パーソナライゼーション
preferences: {
namespace: "nekomata",
key: "user_preferences",
type: "json",
value: {
preferred_brand: "neko" | "tokinoe" | "dog",
default_quantity: number,
preferred_finish: "matte" | "glossy" | "premium",
email_notifications: boolean,
marketing_consent: boolean
}
},
// 📱 マイページ設定
mypage_config: {
namespace: "nekomata",
key: "dashboard_settings",
type: "json",
value: {
photo_grid_size: "small" | "medium" | "large",
order_history_filter: "all" | "by_brand" | "recent",
photo_privacy: "private" | "shared",
download_original: boolean
}
}
}
🔗 D1連携アーキテクチャ
データフロー設計
const dataFlowArchitecture = {
// 👑 Shopify = 単一真実源
shopify: {
role: "Master Data Store",
contains: [
"全顧客情報(PII含む)",
"注文・決済情報",
"写真ファイルメタデータ",
"ブランド設定",
"処理状態の永続化"
]
},
// ⚡ D1 = 高速キャッシュ + 処理状態
d1: {
role: "Performance Cache + Processing State",
contains: [
"Firebase UID → Shopify Customer ID マッピング",
"アクティブセッション状態",
"画像処理キュー状態",
"API制限カウンター(40req/min)",
"統計・分析データ(匿名化済み)"
]
},
// 🌐 R2 = 写真ファイル実体
r2: {
role: "Image File Storage",
contains: [
"アップロード画像(オリジナル)",
"印刷用処理済み画像",
"サムネイル・プレビュー画像"
]
}
}
同期メカニズム
// 🔄 データ同期戦略
interface SyncStrategy {
// リアルタイム同期(Webhook)
realtime: {
triggers: [
"orders/create", // 新規注文
"orders/updated", // 注文状態変更
"orders/paid", // 決済完了
"orders/fulfilled" // 発送完了
],
handler: async (webhook: ShopifyWebhook) => {
// 1. メタフィールド抽出
const metadata = extractMetafields(webhook.data)
// 2. D1キャッシュ更新
await updateD1Cache(metadata)
// 3. 処理状態同期
await syncProcessingState(webhook.order_id)
}
},
// バッチ同期(不整合修復)
batch: {
frequency: "5分毎",
scope: "アクティブセッションのみ",
reconciliation: async () => {
// Shopify ↔ D1 の不整合検出・修復
const inconsistencies = await detectInconsistencies()
await repairInconsistencies(inconsistencies)
}
}
}
📱 マイページ機能設計
購入履歴・写真閲覧
// 🖼️ マイページ写真表示システム
interface MypagePhotoSystem {
// データ取得フロー
dataRetrievalFlow: {
step1: "Firebase UID → Shopify Customer ID",
step2: "Customer Orders取得(メタフィールド含む)",
step3: "LineItem メタフィールドから写真情報抽出",
step4: "R2署名付きURL生成",
step5: "写真グリッド表示"
},
// APIエンドポイント設計
endpoints: {
// 購入履歴取得
"/api/mypage/orders": {
method: "GET",
headers: { "Authorization": "Bearer <firebase_token>" },
params: {
brand?: "neko" | "tokinoe" | "dog",
limit?: number,
cursor?: string
},
response: {
orders: OrderWithPhotos[],
pagination: PaginationInfo
}
},
// 写真詳細取得
"/api/mypage/photo/{order_id}/{line_item_id}": {
method: "GET",
response: {
photo: {
original_url: string, // R2署名付きURL
thumbnail_url: string, // サムネイル
print_ready_url: string, // 印刷用画像
metadata: PhotoMetadata,
print_specs: PrintSpecs,
order_info: OrderInfo
}
}
}
}
}
// 🎨 UI/UX 設計
interface MypageUI {
photoGrid: {
layout: "masonry" | "grid" | "list",
filters: {
brand: "all" | "neko" | "tokinoe" | "dog",
dateRange: DateRange,
status: OrderStatus
},
sorting: "newest" | "oldest" | "price",
actions: [
"再注文",
"オリジナルダウンロード",
"SNSシェア",
"お気に入り"
]
},
photoDetail: {
display: {
mainImage: "高解像度プレビュー",
thumbnails: "複数アングル対応",
metadata: "撮影情報・処理情報",
orderHistory: "この写真の注文履歴"
},
actions: {
reorder: "同じ仕様で再注文",
modify: "仕様変更して再注文",
download: "オリジナル画像ダウンロード",
share: "家族・友人とシェア"
}
}
}
🛡️ セキュリティ・プライバシー設計
PII保護戦略
const privacyProtection = {
// データ分類
dataClassification: {
pii: {
location: "Shopifyのみ",
examples: ["氏名", "住所", "電話番号", "メールアドレス"],
access: "Shopify Admin API経由のみ"
},
nonPII: {
location: "D1キャッシュ可能",
examples: ["Firebase UID", "注文ID", "写真ファイルパス", "処理状態"],
access: "Workers直接アクセス可能"
}
},
// アクセス制御
accessControl: {
mypage: {
authentication: "Firebase token必須",
authorization: "own data onlyポリシー",
dataMinimization: "必要最小限のデータのみ返却"
},
photoAccess: {
method: "R2署名付きURL(1時間有効)",
validation: "注文者本人確認必須",
audit: "アクセスログ記録"
}
}
}
🚀 実装優先順位
Phase 1: 基本メタフィールド実装
priority_1:
- Product: brand_id, print_size設定
- LineItem: photo_file, print_details設定
- Customer: firebase_uid連携
timeline: "2週間"
scope: "基本的な写真注文フロー"
Phase 2: マイページ機能
priority_2:
- Order: processing_state追加
- LineItem: image_processing詳細
- Customer: brand_activity, preferences
- API: マイページエンドポイント実装
timeline: "1ヶ月"
scope: "フル機能のマイページ"
Phase 3: 高度な機能
priority_3:
- 全メタフィールド完全実装
- 不整合検出・修復システム
- 高度なパーソナライゼーション
timeline: "2ヶ月"
scope: "エンタープライズ級機能"
最終更新: 2025-08-23 18:14:53 JST
設計ステータス: PII完全分離アーキテクチャ設計完了
実装準備: Phase 1実装可能、詳細仕様確定済み