事前準備
必要なもの
- Facebookアカウント
- Meta広告アカウント
- Googleアカウント(GAS用)
- スプレッドシート
取得する主な情報
- アプリID
- アプリシークレット
- アクセストークン
- 広告アカウントID
- キャンペーンID、広告セットID、広告ID
Meta開発者アカウント・アプリの作成
ステップ1: Meta for Developersにアクセス
- Meta for Developers にアクセス
- Facebookアカウントでログイン
- 右上の「マイアプリ」をクリック
ステップ2: アプリを作成
- 「アプリを作成」ボタンをクリック
- ユースケースを選択
- 広告データ取得の場合: 「マーケティングAPIで広告パフォーマンスデータを測定」を選択
- その他: 用途に応じて選択
- 「次へ」をクリック
ステップ3: アプリ情報を入力
アプリ表示名: 任意の名前(例: 広告レポート取得)
アプリの連絡先メールアドレス: あなたのメールアドレス
ビジネスポートフォリオ: 該当する場合は選択
- 「アプリを作成」をクリック
ステップ4: アプリIDとアプリシークレットを確認
- 左メニュー「設定」→「ベーシック」を選択
- 以下の情報をメモ(後で使用)
-
アプリID:
123456789 - app secret: 「表示」をクリックして確認
-
アプリID:
⚠️ 重要: アプリシークレットは絶対に他人に教えないこと
アクセストークンの取得
方法1: Graph APIエクスプローラーを使用(推奨)
ステップ1: Graph APIエクスプローラーにアクセス
- Graph APIエクスプローラー を開く
- 右上の「アプリケーション」で作成したアプリを選択
ステップ2: 短期ユーザーアクセストークンを取得
- 「アクセストークンを取得」→「ユーザーアクセストークン」をクリック
- 必要な権限(Permissions)にチェック
広告データ取得に必要な権限:
ads_management
ads_read
- 「アクセス許可を生成」をクリック
- 表示されたトークンをコピー(これが短期トークン)
⚠️ 注意: 短期トークンは約1時間で期限切れ
方法2: 長期アクセストークンへ変換(GASで実行)
ステップ1: GASスクリプトを作成
- Google Apps Script にアクセス
- 「新しいプロジェクト」をクリック
- 以下のコードを貼り付け
// ========== ここを編集 ==========
const SHORT_LIVED_TOKEN = '短期トークンをここに貼り付け';
const APP_ID = 'あなたのアプリID';
const APP_SECRET = 'あなたのアプリシークレット';
// ================================
function getLongLivedToken() {
const url = 'https://graph.facebook.com/v21.0/oauth/access_token?' +
'grant_type=fb_exchange_token&' +
'client_id=' + APP_ID + '&' +
'client_secret=' + APP_SECRET + '&' +
'fb_exchange_token=' + SHORT_LIVED_TOKEN;
try {
const response = UrlFetchApp.fetch(url);
const data = JSON.parse(response.getContentText());
// 長期トークンをスクリプトプロパティに保存
PropertiesService.getScriptProperties().setProperty('LONG_TOKEN', data.access_token);
return data.access_token;
} catch (error) {
Logger.log('エラー: ' + error);
}
}
ステップ2: 実行
- 関数選択で
getLongLivedTokenを選択 - 「実行」をクリック
- 初回は権限確認が表示されるので「権限を確認」→「許可」
- 実行ログ(表示 → ログ)で長期トークンを確認
- 長期トークンをコピーして安全な場所に保存
⚠️ 長期トークンの有効期限: 約60日
必要なIDの取得方法
1. 広告アカウントIDの取得
Meta広告マネージャから取得
- Meta広告マネージャ にアクセス
- URLを確認:
https://business.facebook.com/adsmanager/manage/campaigns?act=123456789 -
act=の後の数字が広告アカウントID - API使用時は
act_123456789の形式で使用
2. それぞれのID取得実装例
const ACCOUNT_ID = 'act_123456789';
const LONG_TOKEN = 'あなたの長期トークン';
const API_VERSION = 'v24.0';
// キャンペーンIDの取得
const campainId = `https://graph.facebook.com/${API_VERSION}/${ACCOUNT_ID}/campaigns?` +
`fields=id,name,status,objective&` +
`access_token=${LONG_TOKEN}`;
// 広告セット取得
const adSetsUrl = `https://graph.facebook.com/${API_VERSION}/${campainId}/adsets?` +
`fields=id,name,status&` +
`access_token=${LONG_TOKEN}`;
const adSetsResponse = UrlFetchApp.fetch(adSetsUrl);
const adSetsData = JSON.parse(adSetsResponse.getContentText());
adSetsData.data.forEach(adSet => {
// 広告取得
const adsUrl = `https://graph.facebook.com/${API_VERSION}/${adSet.id}/ads?` +
`fields=id,name,status&` +
`access_token=${LONG_TOKEN}`;
const adsResponse = UrlFetchApp.fetch(adsUrl);
const adsData = JSON.parse(adsResponse.getContentText());
});
GASでの実装
広告データをスプレッドシートに転記
// ========== 設定情報 ==========
const CONFIG = {
API_VERSION: 'v24.0',
LONG_TOKEN: PropertiesService.getScriptProperties().getProperty('LONG_TOKEN'),
ACCOUNT_ID: 'act_123456789',
CAMPAIGN_ID: 'あなたのキャンペーンID',
SHEET_ID: 'あなたのスプレッドシートID',
SHEET_NAME: 'シート名',
API_SLEEP_MS: 1000, // APIリクエスト間のスリープ時間(ミリ秒)
};
const SHEET_HEADERS = [
'広告セット名',
'広告名',
'取得日',
'clicks',
'impressions',
'spend',
'reach',
'ctr',
'cpc',
'cpm',
'cpp'
];
const INSIGHT_FIELDS = [
'clicks',
'spend',
'impressions',
'reach',
'ctr',
'cpc',
'cpm',
'cpp'
];
// ==============================
/**
* メイン関数:広告インサイトデータをスプレッドシートに取得
*/
function getAdInsightsToSheet() {
try {
const yesterday = getYesterdayDate();
// 広告セット一覧を取得
const adSetsData = fetchAdSets();
const rowsToWrite = collectAdInsights(adSetsData, yesterday);
writeToSheet(rowsToWrite);
Logger.log('処理完了: ' + new Date());
} catch (error) {
Logger.log('エラーが発生しました: ' + error.message);
throw error;
}
}
/**
* 広告セット一覧を取得
* @returns {Object} 広告セットデータ
*/
function fetchAdSets() {
const url = buildGraphApiUrl(
`${CONFIG.CAMPAIGN_ID}/adsets`,
{ fields: 'id,name' }
);
return fetchFromApi(url, '広告セット取得');
}
/**
* 指定された広告セットに紐づく広告一覧を取得
* @param {Object} adSet - 広告セットオブジェクト
* @returns {Object} 広告データ
*/
function fetchAds(adSet) {
const url = buildGraphApiUrl(
`${adSet.id}/ads`,
{ fields: 'id,name' }
);
return fetchFromApi(url, `広告取得: ${adSet.name}`);
}
/**
* 指定された広告のインサイトデータを取得
* @param {Object} ad - 広告オブジェクト
* @param {string} date - 取得日(YYYY-MM-DD形式)
* @returns {Object} インサイトデータ
*/
function fetchInsights(ad, date) {
const url = buildGraphApiUrl(
`${ad.id}/insights`,
{
fields: INSIGHT_FIELDS.join(','),
'time_range[since]': date,
'time_range[until]': date
}
);
return fetchFromApi(url, `インサイト取得: ${ad.name}`);
}
/**
* Graph API URLを構築
* @param {string} endpoint - APIエンドポイント
* @param {Object} params - クエリパラメータ
* @returns {string} 完全なURL
*/
function buildGraphApiUrl(endpoint, params = {}) {
const baseUrl = `https://graph.facebook.com/${CONFIG.API_VERSION}/${endpoint}`;
// アクセストークンを追加
params.access_token = CONFIG.LONG_TOKEN;
// クエリ文字列を構築
const queryString = Object.entries(params)
.map(([key, value]) => `${key}=${encodeURIComponent(value)}`)
.join('&');
return `${baseUrl}?${queryString}`;
}
/**
* APIからデータを取得
* @param {string} url - リクエストURL
* @param {string} logMessage - ログメッセージ
* @returns {Object} パース済みレスポンスデータ
*/
function fetchFromApi(url, logMessage = 'API取得') {
try {
Logger.log(`${logMessage}中...`);
const response = UrlFetchApp.fetch(url);
return JSON.parse(response.getContentText());
} catch (error) {
Logger.log(`${logMessage}失敗: ${error.message}`);
throw error;
}
}
/**
* 全広告セットからインサイトデータを収集
* @param {Object} adSetsData - 広告セットデータ
* @param {string} date - 取得日
* @returns {Array} スプレッドシート書き込み用の2次元配列
*/
function collectAdInsights(adSetsData, date) {
const rowsToWrite = [];
if (!adSetsData.data || adSetsData.data.length === 0) {
Logger.log('広告セットが見つかりませんでした');
return rowsToWrite;
}
adSetsData.data.forEach(adSet => {
// 広告取得
const adsData = fetchAds(adSet);
Utilities.sleep(CONFIG.API_SLEEP_MS);
if (!adsData.data || adsData.data.length === 0) {
Logger.log(` 広告が見つかりません: ${adSet.name}`);
return;
}
adsData.data.forEach(ad => {
try {
// インサイトデータを取得
const insightsData = fetchInsights(ad, date);
if (hasInsights(insightsData)) {
const row = buildSheetRow(adSet, ad, insightsData.data[0], date);
rowsToWrite.push(row);
} else {
Logger.log(` データなし: ${ad.name}`);
}
} catch (error) {
Logger.log(` エラー: ${ad.name} - ${error.message}`);
}
Utilities.sleep(CONFIG.API_SLEEP_MS);
});
});
Logger.log(`合計 ${rowsToWrite.length} 件のデータを収集しました`);
return rowsToWrite;
}
/**
* インサイトデータが存在するかチェック
* @param {Object} insightsData - インサイトデータ
* @returns {boolean} データの有無
*/
function hasInsights(insightsData) {
return insightsData &&
insightsData.data &&
insightsData.data.length > 0;
}
/**
* スプレッドシート書き込み用の行データを構築
* @param {Object} adSet - 広告セット
* @param {Object} ad - 広告
* @param {Object} insights - インサイトデータ
* @param {string} date - 取得日
* @returns {Array} 行データ配列
*/
function buildSheetRow(adSet, ad, insights, date) {
return [
adSet.name,
ad.name,
date,
insights.clicks || 0,
insights.impressions || 0,
insights.spend || 0,
insights.reach || 0,
insights.ctr || 0,
insights.cpc || 0,
insights.cpm || 0,
insights.cpp || 0
];
}
/**
* スプレッドシートにデータを書き込み
* @param {Array} rowsToWrite - 書き込むデータの2次元配列
*/
function writeToSheet(rowsToWrite) {
if (!rowsToWrite || rowsToWrite.length === 0) {
Logger.log('書き込むデータがありません');
return;
}
// シートデータを取得
const ss = SpreadsheetApp.openById(CONFIG.SHEET_ID);
let sheet = ss.getSheetByName(CONFIG.SHEET_NAME);
const lastRow = sheet.getLastRow();
const startRow = lastRow + 1;
const numRows = rowsToWrite.length;
const numCols = SHEET_HEADERS.length;
sheet.getRange(startRow, 1, numRows, numCols).setValues(rowsToWrite);
Logger.log(`${numRows} 件のデータを書き込みました(行 ${startRow} から)`);
}
/**
* 昨日の日付を取得(YYYY-MM-DD形式)
* @returns {string} 昨日の日付
*/
function getYesterdayDate() {
const date = new Date();
date.setDate(date.getDate() - 1);
return formatDate(date);
}
/**
* 日付をYYYY-MM-DD形式にフォーマット
* @param {Date} date - Dateオブジェクト
* @returns {string} フォーマットされた日付文字列
*/
function formatDate(date) {
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, '0');
const day = String(date.getDate()).padStart(2, '0');
return `${year}-${month}-${day}`;
}
トリガー設定手順:
-
GASエディタで「トリガー」アイコン(時計マーク)をクリック
-
「トリガーを追加」をクリック
-
設定
- 実行する関数:
getAdInsightsTosheet - イベントのソース:
時間主導型 - 時間ベースのトリガー:
日付ベースのタイマー - 時刻:
午前2時〜3時
- 実行する関数:
-
「保存」をクリック
トラブルシューティング
エラー1: Invalid OAuth access token
原因: トークンが無効または期限切れ
解決方法:
- 新しい短期トークンを取得
- 長期トークンに変換し直す
- コード内のトークンを更新
エラー2: User request limit reached (Error Code 17)
原因: APIリクエスト制限に到達(一時的)
エラー3: Exception: Invalid argument: URL
原因: URLに特殊文字が含まれている
解決方法:
// フィルター条件をエンコード
const adFilter = encodeURIComponent(JSON.stringify([
{
"field": "effective_status",
"operator": "IN",
"value": ["DELETED", "ARCHIVED"]
}
]));



