JavaScriptで生成される動的なリンクを別タブで開く方法

外部サービスを埋め込む際、JavaScriptによって生成される動的なリンクには、同じタブでページを開く仕様のものがあります。外部サイトへのページ遷移となるため、自サイトからの離脱リスクを最小限に抑えるには、別タブで開くように設定することが望ましいです。
JavaScriptで生成された動的なリンクが同じタブで開かれる場合、JavaScriptを使用することで別タブで開くように実装できます。
アフィリエイトリンク、例えば、もしもアフィリエイトのかんたんリンクでは、各サービスの商品ページへのアクセスは別タブで開く仕様となっています。
YouTubeの埋め込みプレーヤーや各種SNSの埋め込みウィジェットなどでも、モバイル端末ではアプリで開いたりしますが、PCでは同じタブで開く場合があります。
JavaScriptで生成された動的なリンクでなくてもコードを編集して対応することもできますが、その都度作業をするのも大変です。
ここでは、JavaScriptで生成される動的なリンクを別タブで開く方法についてご紹介します。
別タブで開く処理を実装する
まずは、JavaScriptで動的に生成されたHTML構造を確認し、リンクのaタグの親要素に付与れているクラス名を確認しておきます。
ここでは、もしもアフィリエイトのかんたんリンクを例に見ていきます。
もしもアフィリエイトのかんたんリンクでは、商品ページへのリンクがある詳細のコンテンツブロックに「easyLink-info」をいうクラス名が付与されています。このクラスのブロック内のaタグを対象に処理を実装します。
以下、サンプルコードになります。
JavaScript
document.addEventListener('DOMContentLoaded', async function() {
// アフィリエイトリンクの読み込み完了を待機
await new Promise(resolve => {
const checkAffiliateLinks = setInterval(() => {
const easyLinks = document.querySelectorAll('.easyLink-info a');
if (easyLinks.length > 0 && Array.from(easyLinks).every(link => link.href)) {
clearInterval(checkAffiliateLinks);
resolve();
}
}, 500);
});
// アフィリエイトリンクの読み込み完了後に target="_blank" を設定
const easyLinks = document.querySelectorAll('.easyLink-info a');
easyLinks.forEach(link => {
link.setAttribute('target', '_blank');
});
});
上記のJavaScriptコードは、Webページ上のアフィリエイトリンク(easyLink-info クラスを持つ要素内のaタグ)に対して、target=”_blank” を追加する処理を行うものです。
まずは、DOMContentLoadedイベントリスナー「document.addEventListener(‘DOMContentLoaded’, async function() { … });」で、ブラウザがHTMLドキュメントの初期ロードと解析を完了した時点で実行するようにします。async キーワードにより、関数が非同期処理を行うことを宣言し、内部でawait式を使用できるようにします。
アフィリエイトリンクの読み込みタイミングが不定で、Webページの応答性を保つために非同期処理を行います。
「await new Promise(resolve => { … });」では、Promiseを使用して、アフィリエイトリンクの読み込み完了を待機。setIntervalを使用して、一定間隔(500ミリ秒)でアフィリエイトリンクの読み込み状態を確認します。
「document.querySelectorAll(‘.easyLink-info a’);」で、easyLink-infoクラスを持つ要素内のすべてのaタグを取得します。
そのあとのif文は、アフィリエイトリンクが1つ以上存在するか、すべてのアフィリエイトリンクにhref属性(リンク先URL)が設定されているかをチェックします。
条件が満たされたら、clearIntervalでsetIntervalを停止し、resolve()を呼び出してPromiseを完了させます。
アフィリエイトリンクの読み込み完了後(確認後)は、target=”_blank”の設定します。
「const easyLinks = document.querySelectorAll(‘.easyLink-info a’);」で、アフィリエイトリンクの要素を取得して変数に格納。「easyLinks.forEach(link => { link.setAttribute(‘target’, ‘_blank’); });」で、取得したすべてのアフィリエイトリンクに対して、target=”_blank”を設定します。

これにより、リンクが新しいタブで開かれるようになります。
しかし、上記のプログラムで気になるのは、常に対象のセレクタを探し続けることです。
もし対象のセレクタが存在しない場合、今回の例でいくとアフィリエイトリンクを設定していないページの場合は、読み込み完了を待機の処理が実行され続けるということになります。
JavaScriptのプログラムが走り続けると、ユーザーの端末に負担がかかるので、一定時間後にプログラムを停止するようにタイムアウト処理を追加するといいでしょう。
タイムアウト処理の追加
setTimeoutを使用してタイムアウト処理を追加することで、一定時間経過後に処理を停止させることができます。
以下、タイムアウト処理の追加したプログラムになります。
JavaScript
document.addEventListener('DOMContentLoaded', async function() {
try {
// アフィリエイトリンクの読み込み完了を待機(タイムアウト付き)
await new Promise((resolve, reject) => {
const timeoutId = setTimeout(() => {
clearInterval(checkAffiliateLinks);
reject(new Error("アフィリエイトリンクの読み込みがタイムアウトしました。"));
}, 5000); // 5秒後にタイムアウト
const checkAffiliateLinks = setInterval(() => {
const easyLinks = document.querySelectorAll('.easyLink-info a');
if (easyLinks && easyLinks.length > 0 && Array.from(easyLinks).every(link => link.href)) {
clearTimeout(timeoutId);
clearInterval(checkAffiliateLinks);
resolve();
}
}, 500);
});
// アフィリエイトリンクの読み込み完了後に target="_blank" を設定
const easyLinks = document.querySelectorAll('.easyLink-info a');
easyLinks.forEach(link => {
link.setAttribute('target', '_blank');
});
} catch (error) {
// console.error(error.message);
// タイムアウト時のエラー処理
}
});
try-catch文で、エラーが発生した場合にcatchブロック内の処理が実行できるようにしておくと、アフィリエイトリンクを設定したが読み込みがないといった場合、原因特定に適切な対応ができるでしょう。
全体的には先ほどの流れは同じですが、タイムアウトした時にの処理の追加と停止処理に少し変更が加わるかたちです。
「await new Promise((resolve, reject) => { … });」では、Promiseを使用して、アフィリエイトリンクの読み込み完了を非同期で待機。resolveは成功時、rejectは失敗時に呼び出されます。
setTimeout()では、5秒後にタイムアウトを設定し、タイムアウトとなった場合はcheckAffiliateLinksの処理を停止し、reject()を呼び出してエラー処理を行います。
checkAffiliateLinksの処理では、clearTimeout()とclearInterval()で、読み込み完了またはタイムアウト時に、タイマーとインターバルを停止します。
アフィリエイトリンクの読み込み完了後(確認後)は、target=”_blank”の設定処理となります。
catch()でのエラー時の処理は、必要に応じてコンソールに出力して確認するといいでしょう。
タイムアウト時間(5秒)やチェック間隔(500ミリ秒)は、必要に応じて変更してください。
余談
target=”_blank”の設定は、セキュリティ上の注意点もありますので、rel=”noopener noreferrer”と合わせて使用することをお勧めします。
target=”_blank”を設定する部分
link.setAttribute('target', '_blank');
link.setAttribute('rel', 'noopener noreferrer');
今回のもしもアフィリエイトのかんたんリンクは、rel=”noopener”が設定されていましたので、target=”_blank”の設定のみとしました。
noreferrerについては、アフィリエイトでカウントされない場合もあるようなので、アフィリエイト広告関連のリンクに適用する場合は確認が必要になります。
また、JavaScriptで生成される動的なリンクではなく、iframeなどの埋め込みでなどでセレクタが取得可能であれば、以下のようにシンプルに属性を追加することもできます。
JavaScript
document.addEventListener('DOMContentLoaded', () => {
const sanpleLinks = document.querySelectorAll('.sampleBox a');
sanpleLinks.forEach(link => {
link.setAttribute('target', '_blank');
link.setAttribute('rel', 'noopener noreferrer');
});
});
セレクタ「.sampleBox」や変数「sanpleLinks」の部分を、対象の要素に合わせて指定してください。
最後に
JavaScriptで生成される動的なリンクは、読み込まれたことを確認してからでないと、生成されたHTML構造を編集することが難しい場合がありますので、setIntervalで状況を確認していく必要があります。そうすれば、うまく対象のセレクタに対して処理を実行することができます。今回の場合はリンクを別タブで開く処理となります。
ちなみに、JavaScriptのwindow.open()メソッドを使う方法もありますが、ポップアップブロッカーによってブロックされる可能性もあるので、今回ご紹介したtarget=”_blank”を追加する方法が適策でしょう。
ぜひ参考にしてください。