- 小程序请求数据双向混合加密和防篡改+防重放攻击的实现
前言 大家好,借着中秋放假明日又要上班的这个晚上,平常又没空,趁这个时间点就决定来一篇。 [图片] 我们都知道微信小程序的服务端API上,官方可谓是做足了心思,对用户的数据进行加密,虽然对我们开发者来说似乎是一种麻烦,但是从长远角度来看,是十分有必要的,用户隐私高于一切。 那么在小程序的开发过程中与后端对接接口时是否有想过这样的问题呢? HTTPS真的百分百安全吗? 数据被成功抓包后安全吗? 数据被篡改后还有效吗? 请求被重放后安全吗? 世界上没有绝对安全的系统,但我们可以让它被破解的成本变高。 本篇文章专业性并不高,如果存在错误请大家为我指出来,以免误导别人,谢谢! 以下我们将小程序端称为C端,服务端称为S端,服务端代码是Node.js,仅供参考,但原理都一样,后端可以是其它语言。 思考 围绕着以上的问题,探究一下问题的答案? 本部分只对问题做思考,具体实现请参考下面的实现部分。 HTTPS真的百分百安全吗?只能说是相对安全,当然,在微信小程序的沙箱环境里,HTTPS通信会更加安全,否则官方可能会要求我们对请求加密了对吧。但百密一疏,C端是否存在漏洞,假设C端安全了难道S端就安全嘛?细思恐极,退一万步讲,百分百安全是不存在的,由于篇幅问题相关漏洞大家可以搜索探究。 假设数据被中间人成功抓包,如果数据是明文传输,那么将导致数据泄露,因此对数据进行加密是必要的,但应该如何加密呢?如何做到密钥安全?C端和S端如何进行数据的加解密?RSA和AES加密应该使用哪种加密明文?如何充分发挥RSA和AES两个加密算法的特长? 假设数据被篡改,如果因为请求数据被篡改而导致严重后果,那么很大程度上其实是代码设计有问题,正常设计中安全应被摆在重要的位置,至少不应该出现购买某样商品时是通过C端发送商品价格给S端调起支付那样(只需篡改商品价格即可支付极少的钱购买商品),如果代码设计并不存在严重问题,那么数据被篡改也是不可忽视的,我们需要进行数据签名,让不同的数据拥有唯一的MD5哈希值,如果数据被篡改,通过哈希值即可判断数据是否被篡改,当然也可能会有人问,既然数据被篡改,那攻击者会不会重新生成一个哈希值代替?是的。但是我们有接下来会说到的key,key会作为签名的数据变量之一,由于攻击者并不知道key值因此无法重新签名,key值建议不是固定值而是周期性更换的随机值,例如随着用户的登录态而产生并随之抹除。 假设请求被重放,大部分时候由于数据被加密和防篡改处理过,攻击者并无法直接获得数据或篡改,但如果通过劫持到的登录认证请求的原始数据并重新发起该请求,则攻击者将可能获得重要的认证数据,使得系统将攻击者作为正常用户处理,后续的请求攻击者仍能伪装成正常的用户进行后续攻击。 期望效果 在开始实现之前先看一下完成后的效果,以下是截取了Network中其中一个GET请求发送的数据: [图片] 实际上发送的数据是如下图所示: [图片] 然后是该请求返回的数据: [图片] 实际上返回的数据是如下图所示: [图片] 整个流程: [图片] 实现 由于整个流程在C端的实现上顺序反过来的,因此下面的步骤也将是反向而行。 工具库下载 工欲善其事,必先利其器!这三个库是经过修改压缩的,支持在小程序上使用并且体积可观(总共69.1KB,如果不涉及密码哈希处理只需要前两个库,体积只有65.3KB),接下来的实现操作将会使用到,建议大家可以根据实际情况对功能进行二次封装: CryptoJS.js:点击下载 RSA.js:点击下载 SHA256.js(可选):点击下载 在线的各类加解密工具(可选,可以收藏起来,平时测试挺有用):点击访问 请求数据防重放 要防范请求重放攻击,首先需要了解Unix时间戳 timestamp概念,和时间戳不一样的是它的单位是秒,事实上这个需求也只需要秒级即可。除此之外还将用到另一个值:nonce,它是一个随机产生并只能被使用一次的值,长度自定,请求越频繁长度需要越长(降低同一时间产生相同nonce的几率),C端发送请求时需要将timestamp和生成的nonce加入发送的参数中。那么,如何将两者结合呢?我这为防重放的目标下了一个简单的定义。 同样的请求只能发生一次,且请求必须在规定时间内发出。 何为同样的请求?不是指两次发送的参数一致就是一样的,而是连timestamp和nonce也一样才算是同样的请求。 那么S端如何确认其是同样的请求呢? S端每次接收到一个请求,都会将该请求的nonce存入缓存并保持60秒(这个阈值不一定是60秒,可以根据实际需要定义),时间过后该值将被移除,建议S端采用Redis存储nonce,这样可省去检测和移除nonce的代码。如果S端发现当前请求的nonce存在于已存储的nonce之中,则此请求发生重复,那么timestamp有何用? 如果只使用nonce我们只能保证该请求60秒内不会重复,但60秒后依然任人宰割,这不是要的结果。所以timestamp将用来限制时间,S端时间戳减去C端发送请求的时间戳,得到的差值为N秒,如果N秒大于60秒则此请求过期,那么则可以保证,60秒内因为nonce相同而被判为请求重放,60秒后因为时间差超过而被判为请求已过期,因此确保了请求不会被重放。。 以下展示三种情况: [代码]C端时间戳:1568487720 //2019/9/15 03:02:00 C端NONCE:5rKbMs2Fm3 C端发送请求 -> S端接收请求 S端时间戳:1568487722 //2019/9/15 03:02:02 CS端时间差:1568487722 - 1568487720 = 2 C端NONCE是否存在于缓存:false 【重放校验通过】 [代码] [代码]C端时间戳:1568487722 //2019/9/15 03:05:22 C端NONCE:IzFEs52bAC C端发送请求 -> S端接收请求 S端时间戳:1568487922 //2019/9/15 03:02:00 CS端时间差:1568487922 - 1568487722 = 200 C端NONCE是否存在于缓存:false 【重放校验不通过,请求已过期,因为时间差超过60秒】 [代码] [代码]C端时间戳:1568487720 //2019/9/15 03:02:00 C端NONCE:IxwPHQU0nA C端发送请求 -> S端接收请求 S端时间戳:1568487722 //2019/9/15 03:02:02 CS端时间差:1568487722 - 1568487720 = 2 C端NONCE是否存在于缓存:true 【重放校验不通过,此请求为重放请求,因为nonce已经存在,此请求已经完成,不可重复】 [代码] timestamp和nonce将作为参数参与下面部分的签名。 请求数据防篡改 C端数据签名 首先通过对参数按照参数名进行字典排序(调过一些第三方API的朋友应该明白),假设当前需要传输的参数如下: [代码]{ "c": 123, "b": 456, "a": 789, "timestamp": 1568487720, "nonce": "5rKbMs2Fm3" } [代码] 进行字典排序,参数名顺序应为: [代码]const keys = Object.keys(data); //获得参数名数组 keys.sort(); //字典排序 console.log(key); //["a", "b", "c", "nonce", "timestamp"]; [代码] 参数字典排序后应和参数一起拼接为字符串,至于使用什么拼接符就要与S端商量了,如果参数值是一个数组或一个对象(如c为[1,2,3])那么可以将数据值转为JSON字符串再拼接。以上参数拼接后字符串如下: [代码]a=789&b=456&c=123&nonce=5rKbMs2Fm3×tamp=1568487720 [代码] 下一步是计算拼接字符串的MD5哈希值了嘛? 不是。因为这样拼接的字符串很容易被攻击者伪造签名并篡改数据,这样就失去了签名的意义了。也就是说缺了一个key值。key值又从何而来?上面思考部分有提到建议从登录后发放,并且这个key与该用户的登录态绑定,登录态有效期间,将使用这个key进行请求的签名与验签,至于如何鉴别用户,我们会在最终发送给S端的参数加入一个sessionId作为登录态唯一标识,这里不加是因为这部分数据是需要参与后续的加密的,而sessionId不参与加密。 但是可能又会有一个问题,登录前没有key怎么实现的登录请求?事实上,登录请求并不怕篡改,因为攻击者自己也不知道账号密码,所以无需提供key用于登录请求的签名。 提到登录密码这个需要注意一点,密码不能明文传输,请计算哈希值后传输,S端比对账户密码哈希值即可确认是否正确,同样S端非特殊情况也不能明文存储密码,建议SHA-1或更高级的SHA-256计算后的值,MD5值可能被使用彩虹表(一种为各种常见密码建立的MD5映射表)破解。SHA256计算的库已在上面工具库下载提供。 拼接上我们登录时随机生成的key: [代码]a=789&b=456&c=123&nonce=5rKbMs2Fm3×tamp=1568487720&key=gUelv79KTcFaCkVB [代码] 接下来计算32位MD5哈希值 为什么上面说MD5会被破解而这里却用MD5计算?因为此处计算MD5的目的并不是为了隐藏明文数据,而只是用于数据校验 此处引入了CryptoJS.js [代码]const CryptoJS = require('./CryptoJS'); const signStr = "a=789&b=456&c=123&nonce=5rKbMs2Fm3×tamp=1568487720&key=gUelv79KTcFaCkVB"; const sign = CryptoJS.MD5(signStr).toString(); //a42af0962de99e698d27030c5c9d3b0e [代码] 这么一来我们的数据签名阶段就完成了,然后需要把签名加入参数之中,将和参数一起传输,需要注意的是传输参数无需在意参数名排序。以下是当前的参数处理结果: [代码]{ "c": 123, "b": 456, "a": 789, "timestamp": 1568487720, "nonce": "5rKbMs2Fm3", "sign": "a42af0962de99e698d27030c5c9d3b0e" } [代码] 其实从上面这两部分内容来看,会发现防重放和防篡改是相辅相成的,就像两兄弟一样,少了谁都干不好这件事。 S端验证签名 既然有签名那必定也有验签,验签流程其实就是重复C端的前面流程并比对CS两端得出的签名值是否一致。S端取得请求数据后(假设数据未加密,暂时不讨论解密),将除了sign之外的参数名进行字典排序,sign用一个临时变量存下,然后排好序的参数和C端一样拼接得到字符串。 接下来根据上面部分提到的未加密参数sessionId获得用户登录态并获取到该状态的临时key拼接到字符串末尾,接下来进行MD5计算即可得到S端方获得的签名,此时与请求中携带的sign比较是否一致则可确定签名是否有效,如果不一致返回签名错误。具体流程请参考以下: [代码]C端发送请求 -> S端接收请求 //请求参数为data const _sign = data.sign; //排序并拼接除sign外的参数 let signStr = a=789&b=456&c=123&nonce=5rKbMs2Fm3×tamp=1568487720 const sessionId = ...; //用户的sessionId const sessionData = getUserSessionData(sessionId);//根据sessionId查询用户登录态sessionData并取出key,并拼接到字符串尾部 const key = sessionData.key signStr += key; //MD5计算并比对,代码仅供参考 const sign = crypto.md5(signStr); if(sign !== _sign) { //签名错误! } [代码] 请求数据加解密 有了上面部分的参数处理铺垫后,接下来就该开始本文章最核心的加解密,在这之前我们先了解AES和RSA两种加密算法。了解概念后我们再来思考一下两者的一些特性。 AES加解密需要密钥,除某些模式外还需要提供初始化向量,可使用密钥解出明文,是对称加密算法。 RSA加解密需要一对密钥,分别为公钥和私钥,公钥加密,私钥解密,是非对称加密算法。 两者在加密长文本性能上AES占优势。 根据这些让我们发现,他们可以形成互补关系,RSA加解密安全性高但长文本处理性能不及AES。AES加解密长文本性能优于RSA但需要明文密钥和向量加解密,密钥的安全性成问题。 那么在C端生成随机的AES密钥和向量,使用密钥和向量使用aes-128-cbc加密模式(也可以根据实际需要采用其它的模式)加密真正需要传输的参数(参数则是经过防重放+防篡改处理的参数)得到encryptedData,然后将该密钥使用RSA公钥加密得到encryptedKey,下面我顺便把AES加密的向量也一起加密了得到encryptedIV,这样就完美的互补了对方的缺点,既能够较快的完成数据加密又能保证密钥安全性,两全其美。 整个个加解密流程如下图所示: [图片] 下面的四个小章节将逐一描述流程实现: C端加密数据 C端加密后的数据应如下(并非固定格式,根据自己需要定制): [代码]{ "sessionId": "xxxxxxxx", "encryptedData": "xxxxxx", "encryptedKey": "xxxxxx", "encryptedIV": "xxxxxxx" } [代码] 但RSA公钥又是怎么发放到C端的呢?答案是在登录认证的时候服务器下发的,登录成功时服务器会创建RSA密钥对并把公钥发放给C端,私钥存在服务器上该用户的登录态数据中。流程如下所示: [代码]C端发起登录请求 -> S端接收登录请求 S端登录认证是否通过 true S端生成RSA密钥对 - publicKey , privateKey S端查询相关用户信息 S端生成登录态信息 -> 向登录态信息存入privateKey私钥,登录态信息类似如下 "xxxxxx": { id: "xxxxx", authData: { key: "xxxxxx", privateKey: "xxxxxx" } } S端返回登录态唯一标识sessionId和publicKey公钥以及相关用户信息 -> C端 C端存储登录态信息于本地,后续请求将使用服务器提供的公钥进行加密 [代码] 其中privateKey就是该用户当前登录态所使用的解密私钥,C端通过公钥加密后的AES密钥数据只能用该私钥解密。 如果希望登录阶段的请求也加密,那么可以手动生成一个RSA密钥对,然后客户端放置一个固定的公钥,服务器也使用一个固定的私钥进行登录阶段的加解密。 具体实现如下: 此处引入了CryptoJS.js和RSA.js [代码]const CryptoJS = require('./CryptoJS'); const RSA = require('./RSA.js'); //假设当前已登录成功并获得S端下发的RSA公钥且已存入本地存储 //createRandomStr为生成随机大小写英文和数字的字符串 const aesKey = createRandomStr(16); //生成AES128位密钥 16字节=128位 const aesIV = createRandomStr(16); //生成初始化向量IV const raw = JSON.stringfly({ "c": 123, "b": 456, "a": 789, "timestamp": 1568487720, "nonce": "5rKbMs2Fm3", "sign": "a42af0962de99e698d27030c5c9d3b0e" }); const encryptedData = CryptoJS.AES.encrypt(data: raw, key: aesKey, { iv: aesIV, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7 }); //使用CBC模式和Pkcs7填充加密 const authData = wx.getStorageSync("authData"); //读取本地存的RSA公钥 RSA.setPublicKey(authData.publicKey); //设置RSA公钥 const encryptedKey = RSA.encrypt(aesKey); //RSA加密AES加密密钥 const encryptedIV = RSA.encrypt(aesIV); //RSA加密AES加密初始化向量,是否加密向量可由自己决定 //最后的处理结果 const result = { sessionId: authData.sessionId, encryptedData, encryptedKey, encryptedIV }; [代码] S端解密数据 [代码]const crypto = require('crypto'); const cryptojs = require('crypto-js'); const { sessionId, encryptedData, encryptedKey, encryptedIV } = requestData; const authData = getUserSessionData(sessionId); //获取用户登录态数据 const privateKey = authData.privateKey; const aesKey = crypto.privateDecrypt({ key: privateKey, padding: crypto.constants.RSA_PKCS1_PADDING }, encryptedKey); //使用私钥解密得到AES密钥 const aesIV = crypto.privateDecrypt({ key: privateKey, padding: crypto.constants.RSA_PKCS1_PADDING }, encryptedIV); //使用私钥解密得到AES iv向量 const key = cryptojs.enc.Base64.parse(aesKey); const iv = cryptojs.enc.Utf8.parse(aesIV); const decryptedData = cryptojs.AES.decrypt(encryptedData, key, { iv, mode: cryptojs.mode.CBC, padding: cryptojs.pad.Pkcs7 }); //采用与加密统一的模式和填充进行解密 const { "c": 123, "b": 456, "a": 789, "timestamp": 1568487720, "nonce": "5rKbMs2Fm3", "sign": "a42af0962de99e698d27030c5c9d3b0e" } = decryptedData; //至此解密得到C端传来的数据 [代码] S端加密数据 当S端处理完C端的请求后应加密响应数据,那么加密响应数据应该使用什么密钥呢?既然C端已经将加密的密钥发送过来了,那么干脆将C端使用的AES密钥拿来加密响应数据就可以了。加密的数据传回C端后,C端只需使用该请求所使用的AES加密密钥进行解密即可。响应的加密数据如下: [代码]const cryptojs = require('crypto-js'); const responseData = JSON.stringify(...); //此为S端需要返回给C端的数据 const aesKey = ...; //此为之前C端用来加密数据的AES密钥 const aesIV = createRandomStr(16); //生成初始化向量IV const encryptedData = cryptojs.AES.encrypt(data, aesKey, { iv: aesIV, mode: cryptojs.mode.CBC, padding: cryptojs.pad.Pkcs7 }); //加密响应数据 const encryptedResponse = { "encryptedData": encryptedData, "iv": aesIV }; //得到加密后的响应数据并返回给C端 [代码] C端解密数据 C端接收到S端的响应数据后应对加密的数据进行解密,此次解密就是单纯的AES解密了,使用发起请求时用于加密数据的AES密钥配合响应数据的iv向量对encryptedData进行解密,得到解密后的数据即为S端真正的响应数据。实现过程如下: 此处引入了CryptoJS.js [代码]const CryptoJS = require('./CryptoJS'); const key = ...; //之前用于加密请求参数的AES加密密钥 const { encryptedData, iv } = responseData; const aesIV = CryptoJS.enc.Utf8.parse(iv); const aesKey = CryptoJS.enc.Utf8.parse(key); const decryptedData = CryptoJS.AES.decrypt(encryptedData, aesKey, { iv: aesIV, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7 }); //AES解密响应数据 const { ... } = decryptedData; //得到解密后的响应数据 [代码] 结语 第一次写这么长的文章,可能存在大量纰漏,如果大佬发现问题欢迎指出(`・ω・´)我会马上修改。 也许小程序的运行环境会比我想象中的更安全 也许HTTPS也会比我想象中的更安全 也许Web服务器引擎也比我想象中的更安全 但,安全不总是先行一步的吗?
2019-10-24 - 小程序流量主运营技巧
前言(写给入坑的小白) 本文不涉及任何需要资质的小程序(如:视频类目)。小程序流量主是个人和小微企业主要变现途径之一,满1000人即可开通流量主(登录mp.weixin.qq.com,左侧边栏-推广-流量主-开通即可)。开通后,开发者可从流量主-广告位管理添加广告位,目前有6种广告位。 [图片] 正文(本文约很多字,分为四大主类,手里有1-10个小程序建议全部看完;手里有10个以上小程序,可跳过1、2、3,均为个人观点,不喜使劲喷) 一、小程序定位 小程序定位目前有以下四种,均不需要任何资质,个人(商城除外)/小微企业都可以做,由于本人不擅长文字表达,每个类型只选择一个做分析,谅解。 1、工具类 工具类有很多可以做:题库、技术文档、教程、去水印等。目前最火爆的应该属于疫情相关类的工具,关于疫情数据类小程序不做分析,没资质也没权利,主要说疫情周边可运营的工具。头像口罩,代表小程序:头像加口罩、戴个口罩吧、戴上口罩(每日搜索量约等于2000),可参考以下做法: [图片] 以下为近7日访问数据量 [图片] 盈利方式:流量主 延伸参考:如果仅做头像加口罩的话,那么疫情过后,这个小程序会直线下降,将无任何作用。如果开发者手里目前有类似小程序,可参考“头像加口罩”做法,逐渐去延伸头像周边功能,例: ①、头像加字:头像+数字、头像加V、头像加字、头像加圣诞帽、新年头像边框、头像加福、头像加明星等 ②、聊天背景图、壁纸:武汉加油、卡通、美女(不要漏点太多)、二次元、跑车、科技等 ③、趣味九宫格配图:类似朋友圈9张图,中间获取用户自己头像,周围8张图弄点能吸引用户的等 ④、文字秀:微信昵称下标、上标、个性昵称等 运营分析:如果参考以上4点做法,首先你的程序再疫情结束后,不至于直线下滑,最起码能留住一些用户(UI很重要) 个人建议:工具类的好处就是不需要去长时间盯着后台,建议有想法的开发者,可以入门5-10个左右工具类小程序(功能不要相同)。 推广方式:参考本文第四大板块内容 2、返利类 主流返利平台:淘宝、天猫、拼多多、京东、蘑菇街、唯品会、网易考拉,以下参考 [图片] 盈利方式:返利(主)+流量主(辅) [图片] 基础分析:每个人微信里都会有一个或多个微信群是给你们购物优惠券链接的,他们盈利方式主要是靠每个平台的返利,比如淘宝天猫的叫“阿里妈妈”、拼多多的叫“多多进宝”等 运营分析: ①、平台功能:提供所有优惠券、商品返利、代理入驻、提现(个人可做收款码、企业可对接微信支付到零钱) ②、招代理商、可以给代理商(兼职、宝妈)50%以上的返利 ③、除了商品优惠券之外,可以把返利分给一部分给到用户。首先,用户会花更少的钱买到商品;其次,用户买完东西还会赚点小钱,每个月可提现到微信零钱。这样用户会发生裂变,省钱+赚钱。 个人建议:开发者至少有一个类似的返利小程序,每个月只需运营一天,工作内容一是把用户的返利发给用户&代理商,二是自己去各大平台领取每个月的“工资” 推广方式:参考本文第四大板块内容 3、商城类(个人开发者可跳过) 商城类,本人运营的比较少,每天就10-20单左右,卖啥就不做广告了 盈利方式:差价 基础分析:如果自己手里有一些商品低价资源,可以做一个“综合服务商城类目”,然后去试着用广告主去推一下 运营分析: ①、平台功能:砍价、返利、拼团、回购、入驻、积分、抽奖、游戏营销 ②、广告主曝光&点击报价不要最低,也不要最高,理由就是最低的话,80%的钱会给你推到一些质量很差的微信用户,比如我。 ③、对接圈子,虽然圈子刚起步,不确定能不能做大,万一呢? 个人建议:企业一定要有一个自己的商城,哪怕没人买。这种东西怎么说呢,就好比一个企业站,虽然没什么用,但是得放那儿,万一客户要看呢? 推广方式:参考本文第四大板块内容 4、游戏类(非小游戏) 答题、成语、找茬等类似运营的比较多,可自行搜索,不要认为这是游戏,开发者就望而却步,在线教育类目是可以通过的,这个开发者很多都不知道。以下可参考: [图片] 盈利方式:流量主 基础分析:基本所有的模式都是闯关类型,这种类型的小程序,基本都是用户消磨时间用 运营分析:关卡尽量多,入门、初级、中级、高级,高级模式可以做类比循环,形成无限关卡模式,闯关奖励机制,签到机制等。这种类型的小程序比较方便运营,裂变起来也快。 个人建议:裂变模式一定要有,虽然微信会严格把控这方面功能,但是开发者可以做一些技巧,不要让用户强制或者主动去触发,这样微信对开发者还是很友好的。 推广方式:参考本文第四大板块内容 二、小程序开发 有实力的开发者,自己开发,云开发很快,会前端就可以了,没实力的去正规平台买源码,论坛源码也很多,有部分论坛还是嵌入了比特币勒索,自己做好防护。个人建议:开发者能开发尽量自己开发,后期迭代方便,不要像我一样,50多个小程序80%是买现成去运营的。反正各有各的好处,开发者可自行决定,运营者可选择直接购买源码直接上线运营,前提是自己看好功能是不是和自己要的一样。有些SAAS平台的开发者实力还是可以的,支持定制功能。此处不做广告,自行搜索或者询问朋友。 三、广告位位置及利润 开发者的每个页面广告位一定要分开!一定要分开!一定要分开!这样做的目的是为了分析每个广告位的利润,好去做调整,把收益最大化。 失败案例举例:小程序的主页、个人中心页用同一个banner广告位,这样做出来一点好处都没有,后台只能看到banner收益是多少,看不到是哪个页面收益。极端情况,收益全部再首页,个人中心页没有广告收益,这种情况开发者是不知道的,如果把广告位分开,这种情况可以去优化个人页面,或者主页面换成视频banner。广告位分析页面:流量主--数据统计--广告数据--广告指标明细--细分数据 [图片] [图片] 1、很多人表示,疫情期间流量主收入下滑。这个原因不是因为微信调整流量主收益,根本问题是自己的用户质量。举个例子,当你开通流量主之后,你的用户还是这1000个,假如你第一天收益为100,你很开心,1000用户就能赚100,你第二天就放弃推广了,这样的话,你的用户质量是会逐渐下滑,微信方完全可以认定为你这1000人都是自己的号,去刷广告费的。长此以往下去,你的流量主利润会无限趋向于0。举个栗子: [图片] 2、广告位位置一定要合理好看,但是不代表“流氓”,比如全明星代言的某游戏“元宝无限收一刀999”点哪儿哪充值。开发者需要注意的是小程序的质量,需要用户在每个页面停留的时长最起码30秒,这样一个完整的视频广告才能曝光完。 3、banner广告收益是按有效点击计算的。很多人好几千曝光,但是点击只有几个、十几个,这种情况需要不断去优化接入的场景/位置,提高用户点击意愿。个人技巧:banner广告位尽量不要太多,1-2个就可以。尽量多放几个视频广告位,这样曝光也有收益。格子广告没试过,用过都说不好~ 4、激励广告作为流量主最高收益是有一定道理的,用户为了获取某些奖励是必须观看完整的,所以给开发者建议:用户如果可以获得小程序内某些奖励,可以适当多放一些激励广告位。 5、所有的广告位都是根据用户年龄、爱好等参数去调取相应的广告,开发者不需要去考虑 6、广告收益个人认为:激励》视频》插屏》前贴》banner》格子(格子没试过,暂放倒数第一) 四、小程序推广 尽量做成年人主打的小程序,有些开发者觉得好玩儿,做一些儿童益智类的小程序,你是认为儿童有手机,还是认为家长愿意让孩子玩儿手机呢?这个很不解。没有鄙视的意思,也许是情怀吧~~毕竟我做小程序比较俗,就是为了赚钱。 主流推广方式:公众号引流、截流,由于涉及一些不合常规的内容,本文只说常规操作,剩下的自己领悟,或者可以联系我~ 首先小程序的名字至关重要,一个好的名字可以带来无限的流量,再加上裂变功能(邪恶的微笑)。起名字的时候可以用到的工具:搜索小程序-微信指数,查询关键字,尽量找稳定再1000万以上的搜索量,从关键字中摸索自己的小程序名字。这样用户搜索到你的小程序几率会很高~ 1、工具类核心玩儿法(适用于所有小程序推广):文章引流,截取关键字,火爆主题,比如2019年12月19日庆余年全集泄露、2020年疫情(不要发疫情数据内容,要发一些正能量的有内容文章去引流),我阅读过的文章最低的阅读量8000左右,最高的10万+,据说有好几百万的阅读量。如果你的文章写的好,结尾放一个小广告:为防止疫情蔓延,请给您的头像带上口罩~,啪,一个卡片小程序(或二维码),流量自己想~ 推广对象:18-30岁 2、返利类核心玩儿法: ①、可以参考工具类玩儿法 ②、各大微信群、QQ群,去推广,招代理等方式,或者去买一些基础流量,进行裂变,实际运营看下效果,好继续针对用户群体去推广,建立自己的群体系,群内发商品返利链接。微信好友没人?给你举个例子,我这篇文章发完,如果加个我的二维码,最起码能有100人加我,不是我文章写的有多好,是你永远不知道用户有什么样的目的和需求~ 推广对象:18-60岁 3、商城类核心玩儿法 ①、可参考返利类核心玩儿法,拥有自己的客户群体系,发一些自己的商品还是可以的,一定要带分销体系,你懂得~(最高3级,再高就是传销了) ②、广告主、目前效益个人感觉不明显,每次花1000块钱做广告,利润基本没有,和发广告的钱持平,而且用户留存也不是很高,可能是我的商品比较单一等各方面因素吧,不过赚流量还是不错的。 推广对象:18-30岁(以我的商城为例,还需看商城出售的内容) 4、游戏类核心玩儿法(非小游戏) ①、一个好的名字就够了。举例:精选商品橱窗(腾讯官方),微橱窗(我朋友的)。不得不说,这波流量很高,遗憾的是,他不是火爆的游戏类小程序~ [图片] ②、参考工具类玩儿法,文章引流截流 推广对象:18-40岁 五、小程序矩阵 矩阵一定要有,矩阵一定要有,矩阵一定要有,防截流,底配10个小程序。不是纯矩阵,是微信开发规定,每个小程序可以跳转10个小程序,开发者可以利用这个功能去添加自己的矩阵来获取更多的流量收益,保证自己的用户在自己的矩阵圈活动。 [图片] 写这篇文章主要是给大家传授经验,希望小白能学到点东西,入门后的朋友可领悟到更多运营方法,江湖之大,附月账单有缘再见 [图片]
2020-05-25