vivo H5游戏详情页规范及SDK接入文档

一、版本记录

版本 修改内容
v1.0.0
v1.0.1 新增game-vivo-config.js配置项
  1. 若游戏页使用iframe在详情页内嵌打开,查看目录二、目录三
  2. 若游戏页使用一个新的webview打开,查看目录二、目录四

二、游戏详情页代码包

2.1 详情页规范介绍

详情页设计稿

2.2 代码包目录说明

├── index.html     # 游戏详情页
├── detal/         # 游戏详情页静态资源
│   ├── xxx.js
│   └── xxxx.css
├── manifest.json  # 配置项(配置说明见2.3)
├── game-vivo-config.js  # 同manifest.json(若同manifest与本身项目配置冲突,可以改用这个)
├── icon.png       # 游戏icon(需要替换)
├── sdkAds.js      # 广告通信和API初始化(需自行实现广告逻辑)
├── game.html      # 游戏页面(需要替换)
└── game.js        # 游戏静态资源(游戏页面相关静态资源可在根目录创建game文件进行管理)

2.3 配置项说明

  1. 修改manifest.json/game-vivo-config.js配置项
// mainifest.json
{
  "iframeOpen": true, // 游戏页使用iframe内嵌,更多查看目录三
  "gameInfo": {
    "gameLink": "game.html?a=xxxx", // 根目录的game.html,后面可根据需要拼接参数
    "gameName": "游戏名称",
    "icon": "icon.png", // 请替换根目录下的icon
    "adsenseAccountId": "ca-pub-xxxxxxxxxxx",
    "gameDesc": "游戏介绍",
    "score": 4.30,
    "adList": [ "广告1号位", "广告2号位" ],
    "recommendList": [
        // 8个游戏推荐
      {
        "gameLink": "https://xxxxxx", // 游戏完整链接
        "gameName": "游戏名称",
        "icon": "游戏icon链接"
      }
    ]
  }
}
  1. 替换根目录下的icon.png为当前游戏的图标
  2. 将游戏代码包和详情页代码包合并,记得覆盖根目录下的game.html文件

2.4 代码包下载

更新jssdk版本时,请同步更新代码包

下载

2.5 详情页页面测试

  1. 在详情页链接上添加env=test,详情页的广告将会启用测试模式

三、iframe内嵌打开游戏页

3.1 前提

manifest.json配置"iframeOpen": true

3.2 在game.html向父window发送消息

  function postMessageToParent(params) {
    window.parent.postMessage(
      JSON.stringify(params),
      "https://xxxxxxx" // 父window的域名
    );
  }

3.3 注册消息接收

  window.addEventListener("message", (e) => {
    // 根据消息是否来自父window的域名,判断是否过滤
    if (e.origin !== "https://xxxxxxx") {
      console.warn("其他消息(来自:" + e.origin + ")");
      return;
    }
    console.log(e, "从父window发过来的消息");
    try {
      const paramsFromParent = JSON.parse(e.data);

      // 根据methon类型,执行不同逻辑

    } catch (error) {
      console.log(error);
    }
  });

3.4 调用页面加载性能数据

为了便于平台分析游戏页面加载性能并进行优化,请在游戏首屏加载完成(例如:首个可交互画面展示)调用getPerformanceTrack() 方法,并将性能数据通过postMessage上报给父页面。

由于父窗口无法准确获取 iframe 内页面的性能指标,因此需要在 游戏页面内部执行该方法 并主动上报

  1. 使用示例
  async function reportGameLoading() {
    const performanceData = await getPerformanceTrack();

    postMessageToParent({
      method: "gameLoadingCompleted",
      data: performanceData,
    });
  }

  
  1. 性能采集方法 请将以下getPerformanceTrack方法添加到你的项目中:
function getPerformanceTrack() {
  return new Promise((resolve) => {
    let count = 0;

    function check() {
      if (window.performance && window.performance.timing) {
        const timing = window.performance.timing;

        // 等待 loadEventEnd 产生
        if (timing.loadEventEnd === 0) {
          if (count++ > 100) {
            resolve({});
            return;
          }
          setTimeout(check, 100);
          return;
        }

        const paints = performance.getEntriesByType("paint");
        const fcp = paints?.find((paint) => paint.name === "first-contentful-paint");
        const fp = paints?.find((paint) => paint.name === "first-paint");

        const calc = (end, start) => {
          return end > 0 && start > 0 && end >= start ? end - start : 0;
        };

        const {
          navigationStart,
          responseStart,
          domContentLoadedEventEnd,
          loadEventEnd,
          domainLookupEnd,
          domainLookupStart,
          connectEnd,
          connectStart,
          secureConnectionStart,
          domComplete,
          domLoading,
          domInteractive,
        } = timing;

        const effectiveLoadEventEnd =
          loadEventEnd > 0
            ? loadEventEnd
            : domComplete > 0
            ? domComplete
            : Date.now();

        resolve({
          ttfb: calc(responseStart, navigationStart),
          wst: calc(responseStart, navigationStart),
          tti: calc(domInteractive, navigationStart),
          ready: calc(domContentLoadedEventEnd, navigationStart),
          load: calc(effectiveLoadEventEnd, navigationStart),
          dns: calc(domainLookupEnd, domainLookupStart),
          tcp: calc(connectEnd, connectStart),
          ssl:
            secureConnectionStart > 0
              ? calc(connectEnd, secureConnectionStart)
              : 0,
          dom: calc(domComplete, domLoading),
          fpt: fp ? Math.max(0, parseInt(fp.startTime.toFixed())) : 0,
          fcp: fcp ? Math.max(0, parseInt(fcp.startTime.toFixed())) : 0,
        });
      } else {
        resolve(null);
      }
    }

    check();
  });
}

3.5 谷歌广告相关

自行在sdkAds.js中实现广告通信以及Ad Placement API初始化

广告详细参数介绍请参考谷歌参数用法:https://developers.google.com/ad-placement/apis/adbreak?hl=zh-cn

四、SDK接入说明

4.1 添加 sdk 依赖

<script :src="`https://sdk.vivofungame.com/${version}/index.min.js`"></script>

按照1.2目录的版本号修改version,目前最新版是v1.0.1

4.2 sdk 初始化

在标签中配置

<script>
  window.vivoSDKConfig = {
    adConfig: {
      adTest: true,  // 启用Adsense测试模式,若想启用正式模式请删掉该字段
      adFrequencyHint: '', // 广告展示频次,默认120s
      adClient: "ca-pub-xxxxx"
    }
  }
</script>

4.3 页面加载性能数据:gameLoadingCompleted

请务必把这个方法加到游戏首屏加载完成的时候,上报游戏页面的加载时长数据,便于后续的分析优化

window.vivoSDK.gameLoadingCompleted('game', options)

4.4 游戏内广告

自行实现Ad Placement API广告相关逻辑

五、游戏自动广告规范

5.1 锚定广告:仅限底部,且不允许使用折叠式锚定广告

设置路径:Google AdSense—广告—编辑管理自动广告—重叠式广告格式—锚定广告—高级设置

(1)不勾选:允许折叠式锚定广告等

(2)选择锚定广告位置:仅限底部

参考如下图1:

自动广告规范

5.2 穿插广告

设置路径:Google AdSense—广告—编辑管理自动广告—重叠式广告格式—穿插广告—高级设置

(1)穿插广告展示频次:2分钟

(2)不勾选:允许为穿插广告启用额外触发条件等

参考如下图2:

自动广告规范