GTMでクリックされたリンク内の画像のaltを取得する方法
2020年05月25日
ライター:畑岡 大作

比較的よく見かける計測として、特定(またはすべて)のリンクがクリックされた際に「どのリンクがクリックされたか」を計測しようとするリンククリック計測があります。
通常のテキストリンクであればGoogleタグマネージャ(GTM)でも設定は容易で、Click URL変数(リンクURLを取得する変数)Click Text変数(リンクに含まれる通常テキストを取得する変数)など便利な変数も用意されています。

ただし、残念ながら画像のalt属性などを取得する組み込み変数は用意されていません
そのため、テキストが含まれるリンクであればともかく、テキストを含まない画像のみのリンクについては計測がやや難しくなります。

そこで今回は「リンクに含まれる画像のalt属性の文言」を取得するためのカスタムJS変数についてまとめてみました。
リンククリック計測の設定をGTMでされる際にご参考ください。

なお、本記事で紹介するカスタムJS変数では組み込み変数のClick Element変数とClick Text変数を利用していますので、それぞれ有効化してご利用ください。
また、リンククリックトリガー(「クリック – リンクのみ」トリガー)での動作を前提としていますので、クリックトリガー(「クリック – すべての要素」トリガー)では意図した動作になりません。その点、ご注意ください。

  1. Click Text変数では画像のaltは取得できない
  2. リンク中の画像のalt属性を取得するJS
    1. リンク内に出てきた最初の画像のalt属性を取得するカスタムJS変数
    2. リンク内に含まれるすべての画像のalt属性を取得するカスタムJS変数
    3. リンク内に画像がある場合はテキストと一緒に先頭画像のalt属性も取得するカスタムJS変数 ←おすすめ
    4. リンク内に画像がある場合は先頭画像のalt属性を、なければテキストを取得するカスタムJS変数 ←おすすめ

Click Text変数では画像のaltは取得できない

リンククリック計測を行う際、とても便利な変数としてClick Text変数が存在します。
これはリンクテキストを取得する変数で、例えばGAのイベント計測のラベルなどに入れると「どこのリンクがクリックされたか」をわかりやすく計測することができます。

GAのリンククリックのイベント計測タグの設定例
例えばリンクリック計測する際、イベントラベルなどへセットして使われることが多いです。

そんなClick Text変数ですが、取得されるのはあくまで「リンク内に含まれる(通常)テキスト」が対象となります。そのため、リンク内に含まれる画像のalt属性の文言などは(通常のテキストではないため)取得対象外となります。
つまりバナーリンクなどでは、画像のほかにテキストがaタグ内に含まれていないと返り値が「undefined」になってしまい、どこのリンクなのか判別できないデータになってしまう、という状況が発生します。

テキストを含まない画像リンクをクリックした時、Click Text変数の値はundefinedになる
画像のみのリンクの場合にClick Text変数はundefined(無効な値)になってしまいます。

これを回避するには「クリックされた要素内のimgタグのalt属性を取得する」ための変数を、別途カスタムJS変数として用意する必要があります。

リンク中の画像のalt属性を取得するJS

下記のJSで「リンク内に含まれる画像の一覧」が取得されます。
これは「Click Element変数(=クリックされたリンク)内から画像タグ(imgタグ)を抜き出す」JSで、返り値は「[画像1のHTMLオブジェクト, 画像2のHTMLオブジェクト, 画像3のHTMLオブジェクト]」といった具合の配列になります。

{{Click Element}}.getElementsByTagName('IMG')

ただ、上記はそのままではタグの計測値として利用するには適さないため、別途さらに加工する必要があります。
リンク内に含まれる画像のうち、alt属性のみを抜き出して取得」したい場合は下記のようなアレンジです。もしalt属性ではなくtitle属性が欲しい、といった場合は「.alt」となっている箇所を「.title」などに変えてご利用ください。

[].slice.call({{Click Element}}.getElementsByTagName('IMG')).filter(function(element){
	return element.alt;	// alt属性を持つimgタグだけに絞り込み
}).map(function(element){
	return element.alt;	// alt属性を抜き出し
});

これも配列が返り値となります[‘画像1のalt’, ‘画像2のalt’, ‘画像3のalt’]みたいな値になります)ので、やはりそのままでは計測の値としては利用できません。
そのため、さらに加工を行います。

リンク内に出てきた最初の画像のalt属性を取得するカスタムJS変数

例えば「要素内で最初の画像のalt属性を取得する変数」としたい場合は、下記のようになります。
返り値は「画像1のalt」となります。

function(){
	return [].slice.call({{Click Element}}.getElementsByTagName('IMG')).filter(function(element){
		return element.alt;
	}).map(function(element){
		return element.alt;
	})[0];	// 先頭([0])の画像のalt属性を返す
}

リンク内に含まれるすべての画像のalt属性を取得するカスタムJS変数

また、先頭の画像だけでなく含まれる画像全部のaltが欲しい、という場合は下記のようなアレンジです。
前述の[0]の前までが「クリックされたリンク内の全画像のalt属性一覧」に該当しますので、それを連結(join)して返す形です。返り値は「画像1のalt, 画像2のalt, 画像3のalt」のようになります。

function(){
	return [].slice.call({{Click Element}}.getElementsByTagName('IMG')).filter(function(element){
		return element.alt;
	}).map(function(element){
		return element.alt;
	}).join(', ');	// 含まれる全画像のalt属性を「, 」で連結して返す
}

上記は「, 」を繋ぎ文字にして、画像のalt属性をまとめた文字列を返すカスタムJS変数です。
join(', ')」の箇所が実際の連結処理を行っている箇所ですので、'~'内を変えると繋ぎ文字の変更もできます。

また、例えば「[画像1のalt][画像2のalt][画像3のalt]」みたいに「alt属性の前後を記号で囲いたい」みたいな場合はmap内のreturn行を編集すればOKです。
具体的には下記のようにすると、返り値は「[画像1のalt] [画像2のalt] [画像3のalt]」になります。

function(){
	return [].slice.call({{Click Element}}.getElementsByTagName('IMG')).filter(function(element){
		return element.alt;
	}).map(function(element){
		return '[' + element.alt + ']';	// [alt属性]という具合に各画像のaltの前後へ[~]を入れる
	}).join(' ');	// 含まれる全画像のalt属性を半角スペースで連結して返す
}

リンク内に画像がある場合はテキストと一緒に先頭画像のalt属性も取得するカスタムJS変数 ←おすすめ

さて、実際のリンククリック計測に際して「Click Text変数の代替」として利用したいのであれば、Click Text変数も含む値を返す変数に仕立て上げなければなりません。
例えば、リンク内に画像が含まれていたら「[画像のalt] リンクテキスト」を返し、画像が含まれていなかったら「リンクテキスト(=画像がない場合はClick Text変数と同じ値)を返す変数というのはいかがでしょうか。また、リンクテキストが存在せず画像だけのリンクの場合は「[画像のalt]」のみを返すのが良さそうです。

function(){
	var returnValue = [];
	var imgAlt = [].slice.call({{Click Element}}.getElementsByTagName('IMG')).filter(function(element){
		return element.alt;
	}).map(function(element){
		return '[' + element.alt + ']';	// [alt属性]という具合に各画像のaltの前後へ[~]を入れる
	});
	if(imgAlt.length > 0){
		// ---- クリックされた要素内にimgタグが含まれていた場合
		returnValue.push(imgAlt[0]);	// 含まれる先頭画像のalt属性を返す
	}
	if({{Click Text}}){
		// ---- クリックされた要素内にテキストが含まれていた場合
		returnValue.push({{Click Text}});
	}

	return returnValue.join(' ') || {{Click Text}};	// alt属性とClick Text変数を半角スペースで連結した値を返す
}

今までのサンプルの集大成として、いろいろ組み合わさった形です。

「先頭の」画像、と対象画像を1つに絞っているのはその方が自然かな、という印象によるものですので「いやいややはり全画像のaltを含めたい」という場合は「[0]」の箇所を「.join(' ')」へ差し替えてご利用ください。
その場合の返り値は「[画像1のalt] [画像2のalt] [画像3のalt] リンクテキスト」のようになります。

リンク内に画像がある場合は先頭画像のalt属性を、なければテキストを取得するカスタムJS変数 ←おすすめ

場合によっては「画像のalt+リンクテキスト」ではなく、「画像のalt」または「リンクテキスト」のいずれかにしたい、ということもありますよね。
例えば「altを持つ画像があれば画像のalt」、「無ければリンクテキスト」といった振り分けをしたいのであれば、下記のようなカスタムJS変数になります。

function(){
	var imgAlt = [].slice.call({{Click Element}}.getElementsByTagName('IMG')).filter(function(element){
		return element.alt;
	}).map(function(element){
		return '[' + element.alt + ']';	// [alt属性]という具合に各画像のaltの前後へ[~]を入れる
	});
	return (imgAlt.length > 0) ? imgAlt[0] : {{Click Text}};	// 画像のaltがあったら先頭画像のaltを、なければテキストを返す
}

上記も先のサンプル同様に「先頭画像の」alt属性としています。
もし「全画像の」alt属性にされたい場合は、やはり同様にreturnしている行の「[0]」の箇所を「.join(' ')」のように書き換えてご利用ください。

いかがでしたでしょうか。
地味に「画像しか含まれていないリンク」は存在しがちなため、知っておくとそこそこの頻度で使える場面が出てくると思います。ということを、よくよく考えたらそういえば記事化していなかったことに気付いたため、まとめさせていただいた次第です。

ちなみに最初は「どうせならカスタムテンプレート化したいな」と思ったんですが、権限の都合で実装不可能だったため、カスタムJS変数としての案内になりました。
こういうものこそカスタムテンプレートにできれば嬉しいんですが、セキュリティのための制限ですからまぁ致し方ないですよね。

それはそれとして、Click Text変数(自動イベント変数)に「画像のalt属性も含める」みたいなオプションが実装されたらいいな、とすごく思う私でした。