今まで20年近く個人事業主・フリーランスでしたがご縁があって就職することになり、副業禁止なので、諸々整理中です。
アフィリエイトに関して、各ASPにログインして
- 登録サイトを削除する
※アカウント自体はひとまず残しておく - 提携中のプログラム案件を提携解除する
を進めたのですが、A8にて提携してあるプログラム案件数が膨大な上に、A8は一括提携解除する仕組みが実装されていません。
A8は単に登録しているだけで、アフィリエイター時代も「他のASPに案件がなかった場合のみ、1番最後にA8のアフィリタグを使う」という感じでしたが、たまにメールでアフィリエイト報酬の変更や案件一時停止等のメールがウザいので、この際A8の全案件を提携解除したいと考えました。
AIを使ってもすんなりうまく行きませんでしたが、かなり試行錯誤した結果、自動で一括提携解除できましたので、その手順を共有します。
■注意■
この記事に関する内容は自己責任でお試しください。
※後述のコードは、万が一、エラーで止まっても何かが壊れる事はありません。
また、後述のコードは基本的には、全件提携解除する挙動となっています。
「特定の条件に合致した案件だけ残す」といったコードにはなっていません。
上手く行かない場合は、ご自身あるいはAIで修正して解決してください。
さらに、後述のコードは2026.11.1時点のA8の「参加中プログラム一覧」ページに対応していますが、2026.11.2以降の動作を保証するものではありません。
m(_ _)m
当ページの内容に関して、コメント・お問い合わせ頂いても回答しかねます。
m(_ _;)m
以下、私はFirefoxにて実行しました。
A8の「参加中プログラム」を一括で提携解除する手順
A8にログインして、参加中プログラム一覧ページを開く
↓
「ポップアップとサードパーティによるリダイレクト」を一時的に許可に変更する
↓
F12キーでウェブ開発ツール(デベロッパー ツール・開発者ツール)にて、コンソールを選択し、以下のコードをコピペしてエンター
(async function() {
'use strict';
const WAIT_MS = 1200; // 1件ごとの待機ミリ秒
const processedIds = new Set(); // 処理済みIDの記録(重複処理防止)
// 既存パネルの削除とUIパネル生成
const oldPanel = document.getElementById('a8-cancel-panel');
if (oldPanel) oldPanel.remove();
const panel = document.createElement('div');
panel.id = 'a8-cancel-panel';
panel.style.cssText = `
position: fixed; top: 20px; right: 20px; z-index: 999999;
background: #0f172a; color: #f8fafc; padding: 16px 20px;
border-radius: 8px; box-shadow: 0 10px 25px rgba(0,0,0,0.5);
font-family: sans-serif; font-size: 14px; min-width: 300px;
border: 1px solid #334155;
`;
panel.innerHTML = `
A8 提携一括解除 (完全修正版)
初期化中...
完了件数: 0 件
`;
document.body.appendChild(panel);
const statusText = document.getElementById('a8-status-text');
const subText = document.getElementById('a8-sub-text');
const pauseBtn = document.getElementById('a8-pause-btn');
const stopBtn = document.getElementById('a8-stop-btn');
let isPaused = false;
let isStopped = false;
let successCount = 0;
pauseBtn.onclick = () => {
isPaused = !isPaused;
pauseBtn.textContent = isPaused ? '再開' : '一時停止';
pauseBtn.style.background = isPaused ? '#22c55e' : '#eab308';
pauseBtn.style.color = isPaused ? '#fff' : '#000';
};
stopBtn.onclick = () => {
isStopped = true;
statusText.textContent = '処理を中止しました。';
};
const sleep = ms => new Promise(r => setTimeout(r, ms));
// ドキュメント内から参加中プログラムのIDのみを厳密に抽出する関数
function extractProgramIds(doc) {
const ids = [];
// ご提示いただいた a.actionPgdetail を最優先し、programId= を持つリンクから抽出
const links = doc.querySelectorAll('a.actionPgdetail[href*="programId="], a[href*="/program/detail-partnered?programId="]');
links.forEach(a => {
const m = a.getAttribute('href').match(/programId=([a-zA-Z0-9]+)/);
if (m && m[1] && !processedIds.has(m[1]) && !ids.includes(m[1])) {
ids.push(m[1]);
}
});
return ids;
}
// 子ウィンドウのメインコンテキスト(Main World)に confirm 無効化を注入する関数
function injectConfirmOverride(win) {
try {
win.confirm = () => true;
win.alert = () => true;
const doc = win.document;
if (doc && (doc.head || doc.documentElement) && !doc.getElementById('a8-confirm-override')) {
const script = doc.createElement('script');
script.id = 'a8-confirm-override';
script.textContent = `
window.confirm = function() { return true; };
window.alert = function() { return true; };
Window.prototype.confirm = function() { return true; };
Window.prototype.alert = function() { return true; };
`;
(doc.head || doc.documentElement).appendChild(script);
}
} catch (e) {}
}
// 1件のプログラムを子ウィンドウで確実に解除する関数
async function cancelSingleProgram(pid, subWin) {
const targetUrl = `/program/agreement/partnership-cancel-confirm?programId=${pid}`;
subWin.location.href = targetUrl;
return new Promise((resolve) => {
let isClicked = false;
let ticks = 0;
const timer = setInterval(() => {
ticks++;
try {
if (subWin.closed || isStopped) {
clearInterval(timer);
resolve(false);
return;
}
const currentHref = subWin.location.href || '';
const doc = subWin.document;
if (!doc || !doc.body) return;
// 常に confirm 自動承認をページコンテキストへ注入
injectConfirmOverride(subWin);
// ステップ1: 確認ページ上で「提携を解除する」ボタンを厳密に特定してクリック
if (!isClicked && currentHref.includes('partnership-cancel-confirm')) {
// ご提示の .formActions 内のボタン、かつテキストが「提携を解除する」のものを厳密指定
const buttons = Array.from(doc.querySelectorAll('.formActions button[type="submit"], .formActions button, button[type="submit"]'));
const cancelBtn = buttons.find(b => b.textContent && b.textContent.trim().includes('提携を解除する'));
if (cancelBtn && !cancelBtn.disabled && cancelBtn.getAttribute('aria-disabled') !== 'true') {
isClicked = true;
console.log(` -> [${pid}] 「提携を解除する」ボタンを検出・クリック実行`);
// ページコンテキスト側でも確実にクリック&confirm突破を実行
const clickScript = doc.createElement('script');
clickScript.textContent = `
window.confirm = function() { return true; };
Window.prototype.confirm = function() { return true; };
const btns = Array.from(document.querySelectorAll('.formActions button[type="submit"], .formActions button, button[type="submit"]'));
const target = btns.find(b => b.textContent && b.textContent.trim().includes('提携を解除する'));
if (target) target.click();
`;
(doc.head || doc.documentElement).appendChild(clickScript);
}
}
// ステップ2: クリック後、完了画面(「参加中プログラム一覧へ」ボタン)の出現を検知
if (isClicked) {
const backLink = doc.querySelector('a.btnBack[href*="/program/list/partnered"], a[href*="/program/list/partnered"]');
const bodyText = doc.body.textContent || '';
const isCompletePage = (backLink && backLink.textContent.includes('参加中プログラム一覧へ')) ||
currentHref.includes('complete') ||
bodyText.includes('提携を解除しました') ||
bodyText.includes('解除が完了');
if (isCompletePage) {
clearInterval(timer);
resolve(true);
return;
}
}
// タイムアウト (約15秒)
if (ticks > 60) {
console.warn(` -> [${pid}] タイムアウト (クリック状態: ${isClicked}, URL: ${currentHref})`);
clearInterval(timer);
resolve(false);
}
} catch (err) {
// 画面遷移瞬間の一時的なアクセスエラーは無視
}
}, 250);
});
}
// 子ウィンドウで一覧画面を開き、次のページのプログラムIDリストを取得する関数
async function fetchNextBatchIdsFromSubWin(subWin) {
subWin.location.href = '/program/list/partnered';
return new Promise((resolve) => {
let ticks = 0;
const timer = setInterval(() => {
ticks++;
try {
if (subWin.closed || isStopped) {
clearInterval(timer);
resolve([]);
return;
}
const currentHref = subWin.location.href || '';
const doc = subWin.document;
if (currentHref.includes('/program/list/partnered') && doc && doc.readyState === 'complete') {
const ids = extractProgramIds(doc);
if (ids.length > 0 || ticks > 25) { // 描画完了または約6秒待機後
clearInterval(timer);
resolve(ids);
}
}
if (ticks > 50) {
clearInterval(timer);
resolve([]);
}
} catch (e) {}
}, 250);
});
}
// 作業用の子ウィンドウを1つ起動
const workerWin = window.open('about:blank', 'a8_cancel_worker', 'width=800,height=650');
if (!workerWin) {
alert('ポップアップがブロックされました。ポップアップを許可して再実行してください。');
return;
}
// 初回バッチ:現在の親画面からプログラムIDを取得
let currentBatch = extractProgramIds(document);
if (currentBatch.length === 0) {
statusText.textContent = '解除対象のプログラムが見つかりません。';
workerWin.close();
return;
}
// 全ページ(232件)がなくなるまで自動ループ
let batchNumber = 1;
while (currentBatch.length > 0 && !isStopped) {
console.log(`%c=== バッチ ${batchNumber} 開始 (${currentBatch.length}件) ===`, 'color: #38bdf8; font-weight: bold;');
for (let i = 0; i < currentBatch.length; i++) {
if (isStopped) break;
while (isPaused) {
statusText.textContent = `一時停止中 (累計 ${successCount} 件完了)`;
await sleep(500);
if (isStopped) break;
}
if (isStopped) break;
const pid = currentBatch[i];
processedIds.add(pid);
statusText.textContent = `処理中: ${pid} (現在バッチ ${i + 1}/${currentBatch.length})`;
const ok = await cancelSingleProgram(pid, workerWin);
if (ok) {
successCount++;
subText.textContent = `完了件数: ${successCount} 件 (直近成功: ${pid})`;
console.log(`%c[解除成功] 累計 ${successCount} 件目: ${pid}`, 'color: #10b981; font-weight: bold;');
} else {
console.warn(`[スキップ] ${pid} の解除完了を確認できませんでした。`);
}
await sleep(WAIT_MS);
}
if (isStopped) break;
// 1ページ分が終わったら、子ウィンドウを一覧画面へ戻して残りのプログラムIDを自動取得
statusText.textContent = '残りの参加中プログラムを確認中...';
await sleep(1000);
currentBatch = await fetchNextBatchIdsFromSubWin(workerWin);
batchNumber++;
}
if (!workerWin.closed) workerWin.close();
if (!isStopped) {
statusText.textContent = `全プログラムの解除が完了しました!(計 ${successCount} 件)`;
subText.textContent = '3秒後に一覧画面を最新状態に更新します...';
await sleep(3000);
window.location.reload();
}
})();[/escape-html]※万が一、エラーで止まっても何かが壊れる事はありません。その場合は、ページの再読み込みでコンソール初期化、あるいはブラウザを再起動してください。
↓
終わるまで放置
体感で1プログラムを提携解除するのに3秒くらいかかります。2.5秒くらいかも。
私の場合、参加中プログラムが約250件あったので、10分ちょっとかかりました。
いくつかのプログラムは自動提携解除できませんでした。
なぜか失敗した
- Amazon.co.jp成果反映用
の1件は、手動で提携解除しました。
提携解除できない
- 【A8セルフバック】参加申請・成果反映用
- 【A8.net】成果反映用プログラム
の2件は、A8の基本機能(セルフバック・成果計測)として必須の固定プログラムのため仕様上提携解除できず、そのまま残しました。
他の約250件全て、自動で提携解除できました。