Statistical design scheme for buried point of front landing page
In our daily work, we have more or less received such a demand — to report the user behavior trajectory of the landing page at a buried point, which is convenient for the operation students to analyze and optimize. How to make a general buried point JS-SDK? This is the theme of our sharing this time.
Demand analysis
First of all, let’s think about: from the opening of a page to the interaction, where do we need to do some buried points? Starting from the page, we definitely want to know whether the DOM loading of the page is complete, whether the page resources are loaded, button click, popup exposure, click to jump, and which areas of the user scrolling page are reported in the visual area. Our general approach is to embed the code buried point, the advantage of this is to be able to accurately report in their desired location. The downside is that there is too much coupling to the business code. To reduce strong coupling, we can add reported attributes to tags that need to be buried, and then hand all the reporting logic to our tracer.js.
Burial site design
Since we want to reduce the strong coupling of our code, we completely separate the logic about reporting from the business code.
- Demand forecast
We used to code the embedding like this:
track({
id:' '.msg:' '.type:' '
});
Copy the code
Once the project gets big, it’s likely to get messy, so we can bury it in the following format:
<div id="root" trace-name="land_root" trace-id="1">
<div class="button" trace-name="submit_play" trace-msg="Submit button">Click on the</div>
<div class="button" trace-name="comp_play" trace-msg="Component button">Click the</div>
</div>
Copy the code
By comparison, is it found that this can greatly reduce the strong coupling with the business? Well, let’s make it happen!
- Buried point field
The first step is to define the buried fields according to our business requirements. Here are some fields I have defined:
const types = {
elEventMap: {
document: {
init: 'dt=1000'.ready: 'dt=1001'.exit: 'dt=1002'.winLoad: 'dt=1003',},'[trace-name=land_root]': {
DOMNodeInserted: 'dt=2000',},'[trace-name=comp_play]': {
click: 'dt=3000',},'[trace-name=submit_play]': {
click: 'dt=3001',},'[trace-name=dialog_root]': {
DOMNodeInserted: 'dt=2001'.click: 'dt=3000',},'[trace-name=observer_area]': {
view: 'dt=3004',},... }},Copy the code
To explain why I did it this way, the idea is to use the name of the property as the key, and then use the event that the target object needs to listen for as the value; A bridge object can be bound to multiple events, and each event has a corresponding reporting code. All we need to do is walk through it, bind the events and get the corresponding code.
- Binding of events
Use the type we defined above, and then add it all at once:
let eventsPool = [];
Object.keys(events).forEach((key) = > {
let dom = document.querySelector(key)
for (let k in event) {
function handleEvent(e) {
const tranceName = trace.getElmAttr(e.target, 'trace-name')
if(tranceName) { ... }}if (eventsPool.includes(k)) return;
eventsPool.push(k);
document.addEventListener(k, ['click'].includes(k) ? debounce(handleEvent) : handleEvent)
}
})
Copy the code
Here I am using the event broker and there is a check to see if the event is bound to prevent multiple bindings. Here, to prevent multiple clicks, we use an anti-shake function. And we’ll add a trace-${key}-disabled attribute to the current DOM element to see if the event is triggered. Tracer. js also provides a buried point property triggered by multiple clicks, which can be bound to trace-name=comp_play.
- Checks if the element is loaded
Here we have two schemes, the first is to listen for the DOMNodeInserted event, and the second is to use a timer to listen for the presence of an element and report it if it exists.
- Detects which areas are visible after the user scrolls
Usage is also simple, we simply add trace-name=”observer_area” to the element we want to detect. Top, bottom, left, and right of the current element relative to the viewport satisfy the following conditions:
- The current element relative to the viewport
top
Greater than (-element height /2); - The current element relative to the viewport
bottom
Is less than (viewport height + element height /2); - The current element relative to the viewport
left
Should be greater than zero; - The current element relative to the viewport
right
Should be smaller than the viewport width;
The specific code is as follows:
function computedIsInner(trace, dom) {
let clientW = window.innerWidth || document.documentElement.clientWidth
let clientH = window.innerHeight || document.documentElement.clientHeight
const getBoundingClientRect = dom.getBoundingClientRect()
if (getBoundingClientRect) {
const { left, right, top, bottom, height } = getBoundingClientRect
const isInner =
left >= 0 &&
top >= -height / 2 &&
bottom <= clientH + height / 2 &&
right <= clientW
if (isInner) {
const isDisabled = trace.getElmAttr(dom, `trace-observe-disabled`);
if (isDisabled) return;
trace.setElmAttr(dom, 'observe')
trace.traceEmit(dom, 'observe', {
dt:3004})}else {
trace.removeElmAttr(dom, `trace-observe-disabled`)}}}Copy the code
To ensure that elements already in the visible area are not reported each time, a trace-observe-disabled attribute value is added to the reported area, as long as it is reported only once in the visible area. Note: The code will first check whether the scroll detection function needs to be enabled when running, that is, determine whether the DOM is bound to the attribute trace-name=”observer_area”. If so, the scroll event will be enabled; if not, the scroll event will not be executed. So we have a basic version of the buried point is designed, if more functions can be expanded. That’s all for this share. Thanks for reading. The full project code is available at github.com/774848686/t…