개요
Google Analytics에서 dataLayer를 사용하는데, 제품 노출을 전달할 때 그 제품의 index를 넘겨야 한다.
하지만 tagmanager를 사용하기 위한 dataLayer는 body여는태그 바로 뒤에 삽입해서 jQuery보다 먼저 호출되고만다.
<ul class="product"> <li class="product"> <div class="product"> <div class="product-image"> <a href="/13"></a> </div> <div class="product-content"> </div> </div> </li> <li class="product">...</li> <li class="product">...</li> </ul>
여기서 상품번호 별 li의 index를 어떻게 가져올까?
jQuery
jQuery로는 간단하다.
var position = $('.product-image a[href='/' + {{ product.id }} + '/']&').closest('li.product').index() + 1;
하지만 jQuery를 못 쓰는게 함정
javascript
스택오버플로우에서 루프를 돌지 않고 요소의 index를 받는 함수를 올려놓은 답변을 찾았다.
function getChildNumber(node) { return Array.prototype.indexOf.call(node.parentNode.childNodes, node); }
하지만 내 코드에선 1, 3, 5, 7로 찍혀 나와서 2로 나누고 반올림 해서 수정했다.
function getChildNumber(node) { return Math.ceil(Array.prototype.indexOf.call(node.parentNode.childNodes, node)/2); }
그래서 완성 코드는 이렇게 되었다.
var position = getChildNumber(document.querySelector('.product-image a[href='/' + {{ product.id }} + '/']').parentNode.parentNode.parentNode);
jQuery의 closest같은 경우는 이렇게 구현할 수도 있는데 짜피 한번 쓸거라 걍 parentNode로 올라갔다.
결과
근데 html dom보다 dataLayer가 먼저 불려서 돔 위치를 파악할 수 없어서 결국 fail. 담에 더 파봐야겠다…
(+)160111 추가 내용
jQuery를 GTM 스니펫 위로 올리고, dom ready이후에 추가되는 것들은
$(function() { ... });
제이쿼리로 dom이 만들어진 후에 불리도록 넣었다.
Refer
http://stackoverflow.com/questions/4649699/is-it-possible-to-get-elements-numerical-index-in-its-parent-node-without-loopi
http://stackoverflow.com/questions/22100853/dom-pure-javascript-solution-to-jquery-closest-implementation
dataLayer 푸쉬를 DOM init 이후에 일어나도록 실행문을 조정하면 되지 않나요?
네, jQuery ready로 감싼 코드로 update했습니다. 피드백 감사합니다! (- -)(_ _)