北京云服务器,北京云主机解析
新睿云北京云服务器服务中心为用户提供ecs云服务器、云主机租用、DDOS高防IP、域名注册、对象存储、云数据库等多种互联网应用与营销的一体化全面付服务器。并且对个人用户有扶持政策,提供免费的云服务支持。本着以开放、透明、规范、稳定、高性价比的服务,让企业减少服务器成本,把精力专注于核心业务。
在日常的开发过程中,作为前端的 RD 同学,会经常的去配合 PM 去做一些业务埋点,而且有些埋点还贼复杂,埋点完成还要验收,对于 QA 跟 RD 来说都是一件很麻烦的事。
h5
埋点入侵了业务代码
// 这里有两个问题:1. 入侵了业务 2. 如果 clickReport 报错了,会影响正常的业务代码
const handleClick = () => {
clickReport();
doSomething();
}
携带业务参数过多,在组件间需要重复传递
// 层层传递无形之中增加了组件的复杂度
const Main = () => {
const baseAnalytics = { city: 1, user: 2 };
return (
<div>
<Child1 baseAnalytics={baseAnalytics} />
<Child2 baseAnalytics={baseAnalytics} />
</div>
}
部分复杂的埋点,需要在业务层面做很多额外的操作
目标
减少对业务的入侵
简化埋点的过程
方案
将埋点上报抽象出来 埋点的上报必然跟某个dom节点有关联,比如这个节点曝光了,或者这个节点被点击了。我们如果将我们的信息有规律的放在dom节点里,比如约公共的参数在上层,这样我们只要得到需要上报的节点,在一层一层的向上层查找,就可以将我们的数据聚合,并上报了
代码实现
const mergeLab = (parentLab: any, childLab: any) => {
if (!parentLab) {
return childLab;
}
if (!childLab) {
return parentLab;
}
return { …parentLab, …childLab };
};
// 只支持 曝光 跟 点击 an 为 analytics 简称
export const findAnLabAndReport = (
ele: HTMLElement | null,
anData: any,
eventType = “click”,
anReport
) => {
const eventTypeId = eventType === “click” ? “anClickId” : “anViewId”;
// 查找到 body 算结束
if (!ele || ele === document.body) {
if (!anData.eventId || anData.eventId === “null”) {
return;
}
anReport(anData);
return;
}
const data: any = ele.dataset || {};
let newLab: any;
let newEventId: string | undefined = anData.eventId;
let newPageId: string | undefined = anData.pageId;
if (data.anLab) {
try {
newLab = JSON.parse(data.anLab);
} catch (e) {
console.error(e);
}
}
if (!anData.eventId && data[eventTypeId]) {
newEventId = data[eventTypeId];
}
if (!anData.pageId && data.pageId) {
newPageId = data.pageId;
}
findAnLabAndReport(
ele.parentElement,
{
eventId: newEventId,
pageId: newPageId,
anLab: mergeLab(newLab, anData.anLab)
},
eventType,
anReport
);
};
处理点击事件上报
利用事件冒泡机制,在body上面绑定点击事件,再从event对象中拿到触发点击的节点,将其传递给 findAnLabAndReport即可,这样我们就不在需要再业务代码中增加 clickReport 这样的方法了。
注意:如果click事件被阻止冒泡了,这里就需要手动上传一下
实现效果
document.body.addEventListener(
‘click’,
(e: any) => findAnLabAndReport(e.target, {}, ‘click’, clickReport),
);
const APP = () => {
return (
<div
data-page-id=”PageId”
data-an-lab={JSON.stringify({ userid: -1, cityid: -1 })}
>
<ChildA />
</div>
);
};
const ChildA = () => {
return (
<div
data-an-click-id=”ClickId”
data-an-lab={JSON.stringify({ id: 1, cityid: 2 })}
>
ChildA Click
</div>
);
};
处理曝光事件
利用 intersection-observer 去做埋点曝光,核心还是要将处理的节点传递给我们的 findAnLabAndReport,拿到节点信息后,再将数据一层层聚拢,上报
const viewReportInit = (
domOrDomList: HTMLElement | Array<HTMLElement>,
viewReport,
startObserver = true,
): Boolean => {
if (!domOrDomList || (domOrDomList instanceof Array && !domOrDomList.length) || !startObserver) {
return false;
}
let listerCount = domOrDomList instanceof Array ? domOrDomList.length : 1;
const io = new IntersectionObserver(
(IntersectionObserverEntryList: Array<IntersectionObserverEntry>) => {
IntersectionObserverEntryList.forEach(
(IntersectionObserverEntry: IntersectionObserverEntry) => {
if (IntersectionObserverEntry.isIntersecting) {
const targetEle = IntersectionObserverEntry.target;
io.unobserve(targetEle);
listerCount -= 1;
findAnLabAndReport(targetEle as HTMLElement, {}, ‘view’, viewReport);
if (listerCount <= 0) {
io.disconnect();
}
}
},
);
},
);
if (domOrDomList instanceof Array) {
domOrDomList.forEach((ele: HTMLElement) => {
io.observe(ele);
});
} else {
io.observe(domOrDomList);
}
return true;
};
实现效果
const APP = () => {
// 这里只执行一次,如果有依赖的需要执行多次的话,`会出现多次曝光`
useEffect(() => {
viewReportInit(
Array.prototype.slice.call(
document.querySelectorAll(“.view-observer”) || []
),
data => console.log(data)
);
}, []);
return (
<div
data-page-id=”PageId”
data-an-lab={JSON.stringify({ userid: -1, cityid: -1 })}
>
<ChildA />
<ChildB />
</div>
);
};
const ChildA = () => {
return (
<div
className=”view-observer”
style={{ height: “200px”, backgroundColor: “#f0f0f0” }}
data-an-view-id=”viewIdA”
data-an-lab={JSON.stringify({ id: 1, cityid: 2 })}
>
ChildA
</div>
);
};
const ChildB = () => {
return (
<div
className=”view-observer”
style={{ height: “200px”, backgroundColor: “#red” }}
data-an-view-id=”viewIdB”
data-an-lab={JSON.stringify({ id: 2, cityid: 3 })}
>
ChildB
</div>
);
};
总结
笔者这里只是抛转引玉,具体的业务埋点可以根据自己的业务需求去定制,这里主要是想将埋点与业务代码去解耦,不再对业务代码造成严重的入侵,并且简化埋点的方式。 可以根据上面提供的核心方法 findAnLabAndReport 去做更多的业务定制,比如笔者在业务开发中,定制了 useObserver 这样一个 hook 去做曝光节点。
转载请注明:小猪云服务器租用推荐 » h5埋点指北针