.
  • 最新新闻
  • 安卓手机app开发用什么软件_app开发_大鱼科技
    搅局者来了,他叫小程序(微信、支付宝),也叫直达服务(小米)。江湖的玩法变了。 右下角的墨迹天气,是工具类App里的老炮,用户每天开一次、每次瞅一眼的打开方式,让他很头疼。「这怎么卖广告?」 为了挣钱,他在【天气】下面放了一坨新闻,还搞了个【时景】的UGC体系,提升停留时长。又在【我】的页面放了一堆广告入口。
  • 制作手机app大概费用多少钱_app开发_大鱼科技
    有时为了突出名称的意义,可能会跟品牌不一致,但网民搜索又可能搜索不到,这时关键字优化就很重要了,核心优化点在于:内容描述中必须包含核心关键字,并获得较好排名,如搜索『简历』,你的简历相关的小程序是否比较靠前。
  • 开发一个app需要多少钱费用_app开发_大鱼科技
    微信的表情雨让中国人的社交充满了人情味儿。当你在对话框输入“么么哒”或者“想你了”,聊天页面会掉下相应的表情雨,成为大多情侣互传情愫的标准动作。中国传统情人节日“七夕节”已至,情侣们在微信“秀恩爱”的方式又多了一种——黄金红包。
  • 什么是小程序_小程序开发需要多少钱_app开发_大鱼科技
    什么是小程序:小程序是一种不需要下载安装即可使用的应用,它实现了应用“触手可及”的梦想,用户扫一扫或者搜一下即可打开应用。也体现了“用完即走”的理念,用户不关心是否安装太多应用的问题。应用将无处不在,随时随地可用,但又无需安装卸载。
  • 看牌器 透视在哪里买_app开发_大鱼科技
    这个微信小程序的创意始于2012年,当时仅仅开发了Win平台桌面应用,随着移动互联网发展,开发技术栈难度降低
  • 做一个平台app需要多少钱_app开发_大鱼科技
    访问次数:昨日访问小程序内所有页面总次数,多个页面之间的跳转、同一页面的重复访问计为多次访问。 访问人数:昨日访问小程序内所有页面的总用户数,同一用户多次访问不重复计。 新访问用户数:首次访问小程序页面的用户数,同一用户多次访问不重复计。
  • 一天能赚2万的黑方法_app开发_大鱼科技
    没深思小程序最近一个月内更新7次背后是微信内部前所未有的力度在支持小程序(公众号都不曾有此殊遇),特别是微信刚公布2017年Q1月活账号破9.38亿。面对如此巨大的流量洼地,我们如何借助小程序来低成本/0成本获取用户?
  • 网赌破解器哪里下载_app开发_大鱼科技
    小程序定位 对于公司而言,小程序究竟是一个什么产品定位?以目前的大环境而言,无非就是几个关键点: 蹭一波热点,吸引眼球,做小程序这件事情本身就是一个吸引眼球的事情; 延伸产品线,对已有产品线做一个开辟,确保整个线的完整性; 借助小程序,赶上这趟车,营销导流;
  • 定制一款app大概需要多少钱_app开发_大鱼科技
    很多人不禁要对此举的意义发问:以微信的算法而出的搜索结果,岂不是严重遏制了新生小程序的后来者居上?这样即使定义了关键词,对推广而言并没有实质性的意义?微信官方自然也想到了与之相辅相成的策略,我们甚至可以认为后来的这步棋才是微信的本来目的。那就是于6月中旬首次出现于人们视野中的「搜索关键词广告」
  • 软件外包公司_app开发_大鱼科技
    代码的复杂度是评估一个项目的重要标准之一。较低的复杂度既能减少项目的维护成本,又能避免一些不可控问题的出现。然而在日常的开发中却没有一个明确的标准去衡量代码结构的复杂程度,大家只能凭着经验去评估代码结构的复杂程度,比如,代码的程度、结构分支的多寡等等。当前代码的复杂度到底是个什么水平?什么时候就需要我们去优化代码结构、降低复杂度?这些问题我们不得而知。 因此,我们需要一个明确的标准去衡量代码的复杂度。
  • 热门新闻
开发一个app需要多少钱_app开发_大鱼科技
时间:2021-01-10 20:57:23
开发一个app需要多少钱_app开发_大鱼科技

什么是数据埋点

所谓数据埋点就是应用在规定流程中 对特定行为或事件进行数据采集 。使用采集的数据做用户分析和页面分析,可以获得应用的总体使用情况,为后续优化产品和运营提供数据支撑。常见数据埋点内容包括:访问量、停留时长、曝光量、点击量、跳出率等等。

微信小程序也为我们提供了自定义分析统计,其中包括 API 上报(代码埋点),填写配置(无埋点,只需在公众后台配置)。而第三方统计平台比较有名的就是阿拉丁统计,只需引入集成的 SDK,开发成本低,能够满足大部分的需求。

数据埋点需要分析页面流程,确定埋点需求,选择埋点方式。如果是代码埋点,主要关注触发时机、条件判断、捕获数据,其次要注意是否有遗漏的场景没有做到埋点。代码埋点虽然成本较大(侵入代码),但是精准度较高,能够很好的满足埋点需求。

什么是曝光量

曝光量顾名思义是 指定元素出现在可观察视图内的次数 ,也可以理解为展示量。

通常我们会使用 点击量 / 曝光量 得出 点击率 ,作为衡量一个内容是否受用户喜爱的指标之一。比如,曝光 100 次只有 10 人点击,和曝光 100 次 有 100 个人点击,很明显后者更受用户喜爱。利用这些数据参考,可以推荐更多用户喜爱的内容,以此来留住用户。

交叉观察者

IntersectionObserver 接口,提供了一种异步观察 目标元素与其祖先元素或顶级文档视窗(viewport)交叉状态 的方法,祖先元素与视窗(viewport)被称为根(root)。简单来说就是,观察的目标是否和祖先元素和视窗发生交叉,即进入或离开。

小程序从基础库 1.9.3 开始支持 wx.createIntersectionObserver 接口(组件内使用 this.createIntersectionObserver ),使用此接口可创建 IntersectionObserver对象 。对此接口不了解的可以查看 官方文档 。

基础使用

// 创建实例

let ob = this.createIntersectionObserver()

// 相对于文档视窗监听

ob.relativeToViewport()

.observe('.box', res => {

// res.intersectionRatio 为相交比例

if (res.intersectionRatio > 0) {

console.log('进入页面')

} else {

console.log('离开页面')

}

})

阈值

在创建实例时可以传入一些配置,其中 thresholds (阈值)是比较重要的一项配置,它可以控制触发回调的时机。 thresholds 是一个数字类型的数组,默认为 [0] 。即相交比例为 0 时触发一次回调,下面我们来设置阈值,看看会有什么改变:

// 创建实例

let ob = this.createIntersectionObserver({

thresholds: [0, 0.5, 1]

})

从图上可以看到,元素在相交比例为 0 、 0.5 、 1 都各自触发了一次回调。在统计曝光量设置阈值非常有用,通常我会设置为 1 ,表示元素要完全展示在页面上才会进行记录,这样数据会更加真实准确。

收缩和扩展参照区域

除了阈值之外还有另一项重要的设置,在使用 relativeTo 或 relativeToViewport 规定参照区域时,我们可以传入配置 margins 来收缩和扩展参照区域。 margins 包括 left 、 right 、 top 、 bottom 四个参数配置。

// 创建实例

let ob = this.createIntersectionObserver()

// 相对于文档视窗监听

ob.relativeToViewport({

bottom: -330

})

.observe('.box', res => {

// res.intersectionRatio 为相交比例

if (res.intersectionRatio > 0) {

console.log('进入页面')

} else {

console.log('离开页面')

}

})

上面将参照区域底部收缩 330px,可以理解为整体的区域从底部开始被裁剪 330px,因此元素只有进入页面上半区才会触发回调。

进入正题

经过以上一些介绍,相信大家对交叉观察者的好处和使用都了解的差不多。接下来进入正题 ~

背景

此次我做的项目是资讯类目的小程序,主要用于发布和转载一些学术文章。对于这种资讯的项目,需要通过数据埋点来收集用户的阅读习惯,以此来为用户推荐文章。

埋点方面用微信后台提供的自定义分析以文章为单位进行收集,而我们自己后台会以用户为单位进行收集。前者得出整体用户阅读偏好和文章热度,后者主要精确到用户,分析用户单位的阅读偏好。

改造组件

在分析页面布局和pm的商讨后,多处需要统计曝光量的文章区域展示都大致相同,刚好也在封装的列表组件里。于是将收集曝光量的逻辑都交由组件内部处理。

组件改造:

isObserver

list

以下部分代码省略,只展示主要逻辑:

<block wx:for="{{list}}" wx:key="id">

<view class="artic-item artic-item-{{index}}" data-id="{{item.id}}" data-index="{{index}}">

</view>

</block>

const app = getApp()

Component({

data: {

currentLen: 0

}

properties: {

list: {

type: Array,

value: []

},

isObserver: {

type: Boolean,

value: false

}

},

observers: {

list(list) {

if (this.data.isObserver === false) {

return

}

if (list.length) {

// currentLen 记录当前列表的长度

// 用于计算监听元素的索引,对已经监听过的元素不再重复监听

let currentLen = this.data.currentLen

for (let i = 0; i < list.length - currentLen; i++) {

let ob = this.createIntersectionObserver({

thresholds: [1]

})

ob.relativeToViewport()

.observe('.artic-item-' + (currentLen + i), res => {

// 获取元素的dataset

let {

id,

index

} = res.dataset

if (res.intersectionRatio === 1) {

// 此处收集曝光量,内部处理逻辑会在下面提及

this.sendExsureId(id)

// 元素出现后取消观察者监听,避免重复触发

ob.disconnect()

}

})

}

}

this.data.currentLen = list.length

}

}

})

发现:bug:

理想情况应该是切换到第二个分类打印3个文章,但由于组件开始记录第一个分类列表的 currentLen ,在切换到第二个分类时, currentLen 没有被清除,导致循环长度错误。

解决:首先记录列表第一项的 id ,当监听列表变化,用新列表的第一项 id 作与之比较。若不相等,则表示列表被重新赋值,此时将 currentLen 置为0。

Component({

data: {

flagId: 0,

currentLen: 0

}

properties: {

list: {

type: Array,

value: []

},

isObserver: {

type: Boolean,

value: false

}

},

observers: {

list(list) {

if (this.data.isObserver === false) {

return

}

if (list.length) {

// 比较id

if (this.data.flagId != list[0].id) {

this.data.currentLen = 0

}

let currentLen = this.data.currentLen

for (let i = 0; i < list.length - currentLen; i++) {

let ob = this.createIntersectionObserver({

thresholds: [1]

})

ob.relativeToViewport()

.observe('.artic-item-' + (currentLen + i), res => {

let {

id,

index

} = res.dataset

if (res.intersectionRatio === 1) {

this.sendExsureId(id)

ob.disconnect()

}

})

}

}

// 设置列表第一项id

this.data.flagId = list[0] ? list[0].id : 0

this.data.currentLen = list.length

}

}

})

组件优化

因为需要提前监听文章的相交状态,在 list 传入时就开始循环 observe 。现在假设一个场景,在进入页面时,已经为一些文章注册完成回调,但用户并没有看过这些文章就退出页面。那是不是表示这些实例都没有被 disconnect 。

解决:在 observe 时将每一个观察者实例存入数组,当组件销毁时检查数组中是否有观察者实例,如果有,则调用这些实例的 disconnect 。

Component({

data: {

currentLen: 0,

obItems: [] // 存放实例的数组

},

observers: {

list(list) {

if (this.data.isObserver === false) {

return

}

if (list.length) {

if (this.data.flagId != list[0].id) {

this.data.currentLen = 0

// 取消实例的监听

this.removeObItems()

}

let currentLen = this.data.currentLen

for (let i = 0; i < list.length - currentLen; i++) {

let ob = this.createIntersectionObserver({

thresholds: [1]

})

ob.relativeToViewport().observe('.artic-item-' + (currentLen + i), res => {

let {

index,

id

} = res.dataset

if (res.intersectionRatio === 1) {

this.sendExsureId(id)

ob.disconnect()

// 取消监听后 将实例移出数组

this.data.obItems.shift()

}

})

// 将实例存入数组

this.data.obItems.push(ob)

}

} else {

// 取消实例的监听

this.removeObItems()

}

this.data.flagId = list[0] ? list[0].id : 0

this.data.currentLen = list.length

}

},

lifetimes: {

detached() {

// 组件销毁时 取消实例的监听

this.removeObItems()

}

},

methods: {

removeObItems() {

if (this.data.obItems.length) {

this.data.obItems.forEach(ob => {

ob.disconnect()

})

}

}

}

})

收集处理

现在组件能够收集到曝光文章的ID,剩下的就是往后台发送数据。那么问题来了,难道文章曝光一次就发起一次请求吗?如果不怕和后端同事干架的话,你可以这么做。要知道多次发起请求,服务器:pear:会很大。用户量比较大后,对服务器能够承受的并发量会有很大的考验。所以正确的做法应该是,把收集到的ID缓存起来,在达到一定数量的时候一起发送过去。

接下来对收集的数据做些处理:

// 这个上面收集曝光量的函数

sendExsureId(id) {

if (typeof app.globalData.exposureIds === 'undefined') {

// exposureIds 是定义在全局用于存放曝光文章 ID 的数组

app.globalData.exposureIds = []

}

app.globalData.exposureIds.push(id)

// 当数组到达 50 个,开始上报数据

if (app.globalData.exposureIds.length >= 50) {

wx.$api.recordExposure({

// 因为 ID 比较多,我和后端约定好使用逗号分隔

ids: app.globalData.exposureIds.join(',')

})

// 上报后清空数组

app.globalData.exposureIds = []

}

}

看起来好像实现到这里就大功告成,但是我们还要考虑一种情况。假如用户只看了 40 个就退出小程序,而上报条件是达到 50 个才会发送数据,那么这部分有用的数据就会被丢失。因为小程序没有回调能够监听到小程序被销毁,这里只能使用小程序的 onHide 函数来做些事情。当小程序进入后台时 onHide 函数就会被执行,此时可以在函数里上报数据。

App({

onHide() {

if (this.globalData.exposureIds.length) {

wx.$api.recordExposure({

ids: this.globalData.exposureIds.join(',')

})

this.globalData.exposureIds = []

}

}

})

写在最后

说实话,在埋点这方面的知识不算很熟悉,业务场景也比较简单。因为没有大佬指导,也是看着需求往这方面去做,有哪里错误或遗漏请指出。