HTML5 广告教程(三)

原文:HTML5 Advertising

协议:CC BY-NC-SA 4.0

九、应用内广告

在回顾了关于移动网络广告的第八章之后,是时候开始了解广告商是如何将他们的广告带入新兴的应用世界的。这些应用可以是任何东西,从用户从应用商店下载的手机应用到游戏机或智能电视上的应用。我将讨论每种设备和操作系统的不同环境,并讨论所有环境的使用案例。我将回顾软件开发工具包(SDK)和它们如何参与广告服务,以及广告如何在应用中比在移动网络环境中提供更丰富的功能。我将讨论 SDK 提供商,如 AdMarvel、Medialets 和 Millennial Media,它们提供应用内广告,我将重点讨论 IAB 的解决方案和标准,以及 ORMMA 和 MRAID API。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 注意复习本章时请记住,SDK 和应用是会变化的。本章介绍了当前应该做什么,但是随着 SDK 供应商和内容所有者更新他们的 SDK 或使用其他供应商来传播他们的广告,信息可能会发生变化。

移动应用

移动应用是在您的移动设备上运行的本地应用。你可以把它们想象成微软 Office 或 Adobe Photoshop 之类的应用,它们原本在你的台式电脑上运行,但现在却在你的手机或平板电脑上运行。使用移动应用,而不是强迫用户在浏览器中访问 URL 此外,通过提供应用,内容所有者可以完全控制他们的应用,因为它位于设备浏览器之外。应用开发人员通过使用操作系统所依赖的底层代码来创建这些“应用”。对于苹果 iOS 来说是 Objective-C,对于安卓来说是 Java。拥有这些技能的开发人员可以为自己创造一个非常有利可图的职业生涯,为生产力、娱乐甚至游戏开发应用。至少可以说,应用市场正在蓬勃发展,因为 2011 年应用内购买占了 9.7 亿美元的销售额。到 2015 年,这一数字预计将增长到 56 亿美元。Juniper Research 在 2012 年报告称,到今年年底,应用内广告将达到 24 亿美元。到 2015 年,这一数字将飙升至 71 亿美元。这些应用获得了大量的浏览量,因为人们可以在任何时候花很少的费用甚至免费将它们下载到他们的设备上。这当然给应用市场带来了很多关注,以及用户抓住它们是多么容易。

在苹果的应用商店、谷歌的 Play marketplace 和黑莓的应用世界等各种应用商店中,有近百万种不同的应用可供选择;每款应用的功能和价格都各不相同,甚至可以免费进行应用内购买。在接下来的部分中,我将介绍一些领先的应用市场。

苹果

苹果对移动应用市场并不陌生。通过 iOS 和苹果应用商店,用户可以浏览超过 50 万个应用,而且大多数应用都是免费的,还附带广告。开发人员过去可以在他们的应用中获取用户的唯一设备标识符(UDID),但苹果公司删除了这一功能,因为它对用户的隐私问题构成了威胁。基本上,拥有一个用户 UDID 可以让应用开发者通过他们的应用更好地将广告商的信息传递给正确的客户。将位置、时间和兴趣等信息都绑定到一个唯一的设备 ID 或哈希,这意味着广告商可以更好地了解谁在何时查看他们的广告内容。虽然 UDIDs 现在不允许应用在 iOS 中访问广告,但从 iOS 6 开始,还有另一个广告标识符,允许应用通过类似的方式更好地定位。此外,甚至有一个称为 open UDID 的开放 UDID 的倡议,它将被所有设备访问,但它尚未真正起飞(github.com/ylechelle/OpenUDID)。

苹果凭借在这样一个受控的开发者环境中提供的优质应用数量,在应用市场上几乎占据了至高无上的地位。再加上苹果设备的爆炸性增长,这意味着应用是一个非常有价值的市场。图 9-1 显示了 eMarketer 对美国 iPad 用户未来三年的预测。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 9-1。2010 年至 2015 年美国 iPad 用户(数据来源:eMarketer.com)

图 9-1 表示,到 2015 年,大约 9000 万美国用户将接触 iPad 平板电脑并与之互动。随着许多人转向基于平板电脑的体验,而不是传统的桌面应用,预计会看到更多的应用和广告商进入这一领域。

机器人

谷歌的 Android 是另一个主要的竞争应用操作系统。截至去年,谷歌拥有全球最多的每台设备操作系统安装量,许多人认为这是因为它提供了一个稳定和开放的操作系统,可以安装在许多制造商的设备上,如三星、LG、摩托罗拉和其他公司。谷歌提供了与苹果应用商店非常相似的体验,在安卓设备上下载和安装应用;谷歌的商店叫做 Google Play(play.google.com/store/apps)。从安卓设备上,用户可以浏览近百万个应用,包括免费和付费的。就像它的竞争对手苹果一样,由于许多应用都是免费提供的,谷歌应用通常是由基于广告的模式推动的。

关于 Android,需要注意的一件重要事情是,它的操作系统版本在其用户群中有很大差异,这就是为什么对于 Android,你经常会听到碎片化。这种碎片化的出现是因为所有不同的操作系统版本,以及用户无法或缺乏兴趣采用最新版本。我说“无法”是因为许多设备无法更新到最新版本的 Android,这使得其用户群非常多样化。这反过来为开发人员和设计人员创造了大量额外的工作,他们需要创建原生应用和基于 HTML5 的广告。这是 iOS 对开发者保持很大吸引力的主要原因之一;它的用户群采用(并且能够)非常快速地安装最新的操作系统,这给了开发者一个公平的竞争环境来部署内容。为了更好地理解这种碎片化,请访问all thingsd . com/2012 09 20/usage-of-Apple-ios-6-hits-staggering-levels-on-first-day-available,在那里你会发现 Android 的操作系统采用率与苹果的 iOS 相比是失败的。

Android 仍然是移动操作系统领域的主要竞争对手,如果你有兴趣为世界上最大的移动操作系统开发应用,请访问 http://developer.android.com/sdk/index.html。

其他人

许多其他移动操作系统也在市场上,包括黑莓的 App World(appworld.blackberry.com)和 Windows Phone 的 store(windowsphone.com/store),但与 iOS 和 Android 相比,它们目前在全球操作系统市场上的份额都非常小。预计黑莓将在 2013 年发布最新最棒的操作系统黑莓 10,这可能是该公司迫切需要的推动力。在blackberry.com/BlackBerry-10阅读更多特色。

根据研究公司尼尔森(Nielsen)的说法,Windows Phone 在 Windows Phone 7 上的起步也很慢,但预计会有很大的变化,因为 Windows 应该会随着 Windows 8 更新而起飞,Windows 8 更新是与微软的第一款平板电脑 Surface 一起发布的。Windows 最初将这一新操作系统的用户界面命名为“Metro ”,但后来移除了 Windows 8 用户界面的这一品牌。黑莓和 Windows 在移动领域仍然具有竞争力,如果你正在制作需要在这些操作系统上的各种应用中部署的广告,你需要继续阅读,以了解如何利用高度分散的移动市场。

应用内广告

你可能已经猜到,有了所有这些应用商店,这些设备上的用户数量,以及免费应用的数量,广告商注意到并将其部分广告支出转移到这个新兴的数字渠道只是时间问题。嗯,你完全正确。在为设备开发原生应用时,应用内广告正成为开发者收入流的巨大市场。许多内容提供商和开发者以广告支持的模式免费提供他们的应用。以非常受欢迎的游戏 Word with Friends 为例,这款游戏可以在任何操作系统上运行,有免费版和付费版供用户下载。这两款游戏为最终用户提供了非常相似的体验,除了免费版有广告,付费版没有广告。随着这些流行游戏的数以百万计的下载,广告商注意到人们的目光不再都集中在桌面或电视上,所以他们将广告资金转移到了吸引眼球的地方。

应用内广告其实并不新鲜;事实上,自从 2010 年苹果 iPad“发明”了平板电脑市场以来,广告就一直存在于应用中。例如,广告服务器 PointRoll 在 iPad 向用户发布的第一天提供了如图 9-2 所示的广告单元。图 9-2 展示了一个富媒体 Lincoln 广告,它是通过 text plus(textplus.com)应用在 iPad 上使用 SDK 提供商 AdMarvel 部署的。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 9-2。最早的 iPad 广告之一

就率先上市和创新的平板电脑广告而言,林肯的广告相当具有开创性。用户的体验是点击应用中的静态横幅,他们将被带到一个全屏沉浸式环境,其中有视频、高分辨率图像和多种布局,具体取决于设备的方向。这种体验为更具创新性的广告体验铺平了道路,包括游戏、互动和现场投票。很快,广告商们意识到,你可以在桌面上做的任何事情,也可以带到移动和平板电脑环境中。

随着广告商越来越多地涉足这一媒介,预计未来几年将有更多的资金投入这一市场。事实上,eMarketer 和 Juniper Research 指出,2015 年应用中的广告支出将超过 70 亿美元(见图 9-3 )。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 9-3。2012 年至 2015 年全球移动应用内广告支出(来源:eMarketer.com)

随着未来几年应用内广告支出的增加,现在是学习如何将富广告部署到这些新的分发渠道的绝佳时机。但是现在还不完全是有趣和有利可图的。在跨 oss 开发之前,你需要掌握一些关键的技术要点。你可能会认为现在所有的错误都被解决了,这种情况比你最初从 HTML5 和其他移动设备中学到的要少得多。遗憾的是,事实远非如此,在下一节中,您将了解在处理应用内广告时需要考虑的额外碎片。

sdks

HTML5 中的碎片是非常明显的,正如你在前面的章节中了解到的。在移动 web 领域更是如此,有各种不同的操作系统、版本号和各种级别的 HTML5 兼容性。对于移动应用领域,事情变得更加棘手,因为现在开发人员必须了解哪些应用支持哪些广告平台 SDK 以及 SDK 的版本。许多出版商和应用广告服务器使用软件开发工具包(SDK)来处理许多不同应用环境中各种广告标签的交易和调度。可以将 SDK 视为广告管理系统和用户设备上的应用之间的中介层。由于 SDK 实际上只是包含在原生应用中的一点代码,开发人员需要预见到他们的应用应该或将要在某个时候包含广告。例如,目前一些应用,如脸书、Instagram,甚至 Twitter 都没有广告,因此在其应用的开发中不需要第三方广告 SDK。然而,像华尔街日报今日美国和潘多拉电台这样的应用向用户提供广告,以换取免费内容,无论是音乐、体育还是新闻。这些广告通常是通过发布者端的广告服务器和应用软件开发工具包来传播的。一方面,你有广告服务器的活动管理工具,它允许用户安排和定位他们的标签以及设置基本的发送规则。另一方面,您有一个 SDK,它与活动管理工具进行通信,以便接收预定的特定广告。图 9-4 更好地展示了两端之间的连接。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 9-4。应用和广告服务器之间通过 SDK 进行通信

在图 9-4 中,可以看到应用内容会通过 SDK 向广告服务器发出请求。一旦广告服务器知道是什么应用发出了广告请求,它就会通过 SDK 返回适当的广告内容。所以,你可能会想,必须有一个标准的方法来做到这一点,对不对?好吧,回答你的问题,答案是肯定的和否定的。目前,在移动应用内场景中有许多不同的发行商广告服务器和 SDK,在下面的章节中,你将仔细看看一些更受欢迎的,你将在开发应用内活动时处理的。

苹果的 iAd

苹果自己的 iAd 平台(advertising.apple.com)是更受欢迎的应用内广告网络之一。苹果 iAd 平台允许开发者通过横幅和丰富的全屏广告获得收入,其中苹果出售你的应用中的广告空间,并通过其网络发送广告以填充广告位。然后,当用户查看(印象或与应用中显示的广告互动(活动)时,应用开发者可以获得收入。

苹果 iAd 平台是在 4.0 版本的操作系统中向 iOS 开发者和广告商推出的,过去每个广告活动的价格高达 100 万美元,但由于缺乏初始参与者,价格已经大幅下降。要使用苹果的 iAd 平台,你必须成为苹果开发者和 iAd 网络成员,只有这样,应用发行商或开发者才能控制应用中的广告。有了 iAd,开发者可以使用苹果的免费工具,如 iAd Producer,它为快速构建 iOS 广告提供了一个干净的界面。此外,由于广告是为 iPhone 和 iPad 等 iOS 和苹果设备构建的,开发者可以利用一些真正令人惊叹的应用内功能,例如:

  • 在后台下载应用或 iTunes 内容
  • 将提醒事项直接添加到日历应用
  • 使用联系人列表,在广告中撰写和发送品牌电子邮件
  • 借助 WebGL 支持体验身临其境的 3D 图形(更多关于 WebGL 的信息,请参见第十二章)
  • 在自定义框架中查看在线音频和视频
  • 保存优惠券、条形码、食谱或品牌壁纸
  • 使用地理定位查找附近的商店

除了 iAd 用户可用的丰富功能外,该平台还提供有价值的指标和分析,例如:

  • 印象
  • 龙头和龙头通过率
  • 独特的访问
  • 平均花费时间
  • 浏览量和每次访问的浏览量
  • 互动(观看视频、玩游戏等)
  • 转换和下载

最后,iAd 还提供了一些丰富的受众和设备定位功能,例如:

  • 人口统计数据
  • 应用首选项
  • 音乐、电影、电视和有声读物类型兴趣
  • 位置
  • 设备(iPhone、iPad、iPod touch)
  • 网络(WiFi、3G)

如果你是一个出版商或内容所有者,并希望在你的应用中利用 iAd 平台,我强烈建议你访问developer . apple . com/library/IOs/# DOCUMENTATION/user experience/Conceptual/iAd _ Guide/Introduction/Introduction . html

谷歌的 AdMob*

你可能已经猜到了,谷歌也在这个领域,它的大型移动广告平台叫做 AdMob(google.com/ads/admob)。谷歌在 2009 年以 7.5 亿美元收购了该公司,目前 AdMob 每年运营数十亿条横幅和基于文本的广告展示。它的 SDK 跨 Android、iOS 和 Window Phone 7 应用运行,并在一个界面中管理多个广告网络。AdMob 通过与 Adfonic、BrightRoll、HUNT、iAD、InMobi、Jumptap、Millennial Media、MobFox 等网络合作,提供了一个巨大的广告网络中介,为广告管理提供了一个单一的界面。应用开发人员将 SDK 代码库安装到他们的应用中,并可以通过在环境中提供富媒体广告来获得收入。除了 SDK 之外,AdMob 还直接与 DoubleClick for publishers (DFP)接口,后者允许用户直接通过 AdMob 广告网络填充广告库存。AdMob 允许富媒体,提供利用 HTML5 的高级创意格式,并提供针对特定人口统计和位置的受众。要下载最新的 AdMob SDK,请访问 http://developers.google.com/mobile-ads-sdk/download。例如,对于使用 AdMob SDK 的应用,请访问 http://code.google.com/p/google-mobile-dev。

歌剧广告*

另一个移动广告服务器和 SDK 提供商是 AdMarveladmarvel.com。AdMarvel 隶属于浏览器制造商 Opera,是一家强大的出版商端广告服务器、优化/中介(移动广告交换)和富媒体 SDK 提供商。与 AdMob 非常相似,它提供了一个 iOS 和 Android SDK 以及一个黑莓 SDK。因此,应用开发人员/发行商可以获得最好的服务,并访问其他富媒体提供商,同时减少应用中的 SDK 混乱。通过 AdMarvel 接口,标准目标包括:

  • 时间
  • 地区
  • 设备
  • 操作系统
  • 网络运营商

请注意,自定义目标也是可用的(专门针对 AdMarvel)。这意味着活动经理和开发人员可以根据之前的输入为某些广告标签设置规则,以呈现到用户的设备上。当您想要为特定设备、一天中的某个时间,甚至是手机网络状态提供定制的消息或创意时,这非常有用。

媒体*

另一个流行的移动富媒体广告服务器和 SDK 提供商是 media lets(medialets.com)。Medialets 专门从事移动富媒体,在在线出版商和电子杂志等数字出版物市场都有很大的渗透力。Medialets 提供了自己的 SDK,用于集成到 iOS、Android 和 BlackBerry 应用中,并提供了一套分析工具来衡量您的活动效果。由于 Medialets 是一个在应用环境中工作的 SDK 提供者,它可以提供很好的定位,包括时间、地理位置、应用内容、设备类型和连接状态。

千禧年媒体

千禧传媒(millennialmedia.com)自称是最大的独立移动广告网络,与谷歌的 AdMob 和苹果的 iAd 竞争。Millennial Media 还推出了完整的 SDK (MMSDK ),可以在各种设备上的各种应用中提供富媒体移动广告。您可以下载适用于各种设备操作系统的 MMSDK,包括 iOS、Android、BlackBerry、Windows Phone、PSP 和 WebOS 等等。通过 Millennial Media 的工具,开发人员可以通过实时结果和分析支持交互式移动视频广告、移动富媒体和传统横幅广告。千禧媒体还提供目标定位,包括人口统计、行为、地理位置和背景等。你可以在 http://tools.mmedia.com 的了解更多关于它的工具集(一定要先注册)。

其他人

移动广告网络和提供 HTML5 驱动的富媒体的 SDK 提供商还有很多。对于本书的范围来说,有太多的名字,这是一个不断变化的生态系统。但是为了让你知道其他几个,你可能还需要把你的广告标签放到 Jumptap(jumptap.com)、grey stripe(greystripe.com)和 InMobi(inmobi.com)这样的网络中。请注意,他们可能依赖这里没有提到的 SDK。事实上,某些应用拥有自己的“自制”广告服务 SDK,如 Pandora Music 应用,当服务于此类应用时,应用提供商、SDK 供应商和创意机构需要共同确定需要对平台进行哪些调用,以识别广告的某些丰富功能,如广告是扩展还是关闭。Pandora 对移动领域并不外行,但出于某种原因,它选择不与 iAd、Millennial Media 和 AdMeld 等提供商合作,可能是因为安全问题(cnnmoneytech . Tumblr . com/post/4588292154/Pandora-boots-its-outside-ad-platforms)。

所有这些 SDK 供应商信息的要点是,这些 SDK 需要被您交付的 HTML5 广告创意引用。ad 和 SDK 供应商之间的这种通信是通过 API 进行的,它通常通过 ad 的 JavaScript 代码进行通信。对于扩展、关闭并提供视频和游戏的移动富媒体广告,包含广告的应用需要根据用户交互了解广告处于什么状态。这可能看起来很熟悉,因为我在第七章的中讨论了在出版商的视频播放器中使用 VPAID API。基本上,同样的规则也适用于此,广告需要与发行商的应用进行沟通,这样最终用户的体验才不会不舒服。问题是,这个领域有这么多不同的供应商,很难理解什么样的 API 适用于所有这些供应商,即使存在这样的供应商。这就是移动应用空间中出现碎片的地方。这在不同的网络和设备之间会有很大的不同,这使得广告商很难保证购买的媒体在任何地方都能完美运行。

以一个“家庭酿造”解决方案为例,当使用 Pandora 应用时,你可以使用清单 9-1 中的代码片段在它的移动应用中运行一个基本的扩展/折叠富媒体广告。

清单 9-1 。 潘多拉 App API 示例

<!DOCTYPE HTML>
<html>
<head>
<meta name = "viewport" content = "width=device-width">
</head>
<body>
  <button onclick=expandPandora()>Open Panel</button>
  <button onclick=closePandora()>Close Panel</button>
</body>
<script>
document.addEventListener('DOMContentLoaded', function() {

}, false)

function expandPandora() {
   try {
       PandoraApp.setViewportHeight(300)
   } catch (e) {
       console.log (e + " No PandoraApp Reference")
   };

   initExpand();
}

function initExpand () {
   console.log('initExpand')
}

function closePandora () {
   try {
       PandoraApp.setViewportHeight(50);
   } catch (e) {
       console.log(e + " No PandoraApp Reference")
   };

   closeExpand();
}

function closeExpand () {
   console.log('closeExpand')
}
</script>
</html>

从前面的例子中可以看出,通过 JavaScript 调用使用 Pandora 的 SDK 相当简单,但它只适用于 Pandora。在其他出版商之间投放广告的广告商需要为每个出版商定制广告,从操作上来说,这对于规模和快速周转时间没有意义,因为您可能需要在脚本中创建一个大型条件语句来与所有供应商的 API 接口。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

考虑到这个广告可能会被发送给潘多拉之外的出版商,我喜欢用一个 try/catch 方法来包装我的调用。虽然这不是最佳的编码实践,但它确保了如果 Pandora 对象不存在,代码将记录一条消息并继续运行而不会中断。目前,当你想让一个广告在多个网站和网络上运行时,这是一个很好的做法。同样,这个特定的用例只是针对潘多拉的,但是你可以很容易地看到这是如何迅速失控的!让开发人员添加大量的 try/catch 语句或条件是一项额外的工作和测试,在您可以在什么浏览器、什么设备、什么操作系统版本上使用什么功能之间,将这种 SDK 碎片添加到难题中真的会让您头疼!(还记得广告主是怎么想要规模的吗?)总得有更好的吧?!

奥尔玛和 MRAID

因此,对于所有这些应用,您可能会问自己,“这是怎么回事?在 HTML5 广告开发已经多样化的情况下,我为什么还要担心额外的 SDK 碎片?”嗯,一段时间以来(甚至在我写这篇文章的时候),这种方式一直存在,因为供应商认为他们可以将他们的客户捆绑在一起,使用他们自己专有的 SDK 代码库,从而导致客户被他们的广告服务“卡住”。虽然这是一个非常聪明的商业模式,因为它使开发者很难做出改变,但现实是这不是一个长期的商业模式,因此,我向你介绍奥尔马(ormma.org)和 MRAID(iab.net/mraid)。

开放富媒体移动广告(ORMMA)是一项全行业倡议,旨在让广告商拥有一套通用的规则,用于在各种移动应用平台上显示富媒体广告。ORMMA 是一个 SDK 和 API,允许广告设计人员使用一种通用的方式与 ORMMA 兼容的应用进行交互。应用开发人员需要遵循 ORMMA 规范,以允许广告设计人员将引人注目的富媒体广告添加到他们的应用中。虽然 ORMMA 开始大规模构建移动富媒体,但随着 IAB MRAID 的发布,这已经成为过去。

移动富媒体广告接口定义(MRAID)本质上是 VPAID 对于发行商视频播放器的意义,除了移动应用。它建立在 ORMMA 提出的许多原则的基础上,其唯一目的是缓解设备、应用和广告服务器之间的碎片化,使移动富媒体成为一个有利可图的行业。MRAID 得到 IAB 的坚定支持,并有一个致力于其发展的专门工作组。IAB 认为 MRAID 应该成为移动富媒体广告单元与应用环境通信的事实标准。目前在其第二个版本中,MRAID 允许移动广告开发者利用一组标准功能在广告和应用的 SDK 之间进行通信,例如告诉应用广告将扩展、关闭,甚至播放视频。MRAID 并不意味着践踏 HTML5 或当前的 APIs 相反,它的存在是为了帮助广告设计者进行开发,因为某些 HTML5 碎片可能仍然存在。

MRAID 旨在简化和易于实现,并且不依赖于各种 SDK。事实上,对 MRAID 的唯一要求是应用选择的 SDK 应该是 MRAID 兼容的,并且能够识别来自广告代码内部的 API 调用。这些信息只能来自出版商,或者可能是记录谁是 MRAID 认证的或者不是的 IAB。然而,我前面提到的大多数 SDK 供应商都在努力实现 MRAID 合规性,因此在他们的平台内工作应该会很好。

所以,现在你知道了一点为什么 MRAID 对广告设计师很重要,让我们在下一节和清单 9-2 中回顾一些基本的 MRAID 代码。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 在撰写本文时,标有*的 SDK 部分据说是兼容的,支持 IAB 的 MRAID。

MRAID 电码

既然所有未来的 SDK 都应该是 MRAID 兼容的,那么回顾一下 MRAID 代码 在应用中与兼容 SDK 的接口是值得的。清单 9-2 概述了一个使用基本 MRAID API 函数的基本可扩展广告。

清单 9-2 。 MRAID JavaScript API 示例

<!DOCTYPE HTML>
<html>
<head>
<meta name = "viewport" content = "width=device-width">
</head>
<body>
  <div id='cta' hidden data='http://johnpercival.org'>Click Here</button></div>
  <section id='banner'><button onclick=expandMRAID()>Open Panel</button></section>
  <section id='panel'><button onclick=closeMRAID()>Close Panel</button></section>
</body>
<script>
function checkMRAID (){
     if (mraid.getState() != 'ready') {
          console.log("MRAID Ad: adding event listener for ready");
          /* mraid still loading, registering for ready event */
          mraid.addEventListener('ready', init);
     } else if (mraid.getState() === 'ready') {
         console.log("MRAID Ad: already ready, calling init");
         init();
     } else {
         console.log("MRAID Ad: I think its ready, calling init");
         init();
     }
}

function init () {
     mraid.removeEventListener('ready', init);

     console.log("Mraid Version = " + mraid.getVersion());
     console.log("Mraid Placement Type = " + getPlacementType());

     mraid.setExpandProperties({
        width : 320,
        height : 480,
        useCustomClose : true
     });

     mraid.addEventListener('error', handleErrorEvent);
           mraid.addEventListener('stateChange', handleStateChangeEvent);

     document.getElementById('cta').removeAttribute('hidden');
     document.getElementById('cta').addEventListener('click', function() {
        var url = document.getElementById('cta').getAttribute('data');
        openBrowser(url);
     });
}

function expandMRAID () {
     try {
         mraid.expand();
     } catch (e) {
       console.log(e + " No MRAID Reference")
     };
}

function closeMRAID () {
     try {
         mraid.close();
       } catch (e) {
         console.log(e + " No MRAID Reference")
     };
}

function handleStateChangeEvent(state){
     switch (state) {
         case "default":
              document.getElementById('banner').style.display = 'block';
              document.getElementById('expandable').style.display = 'none';
              break;
         case "expanded":
              document.getElementById('banner').style.display = 'none';
              document.getElementById('expandable').style.display = 'block';
              break;
     }
     console.log("State - " + state + " at handleStateChangeEvent");
}

function openBrowser(href) {
     try {
         mraid.open(href);
     } catch (e) {
        console.error(e);
     } finally {
          window.setTimeout('location.href="' + href + '"', 150);
     }
}

function handleErrorEvent (message, action){
  var msg = "MRAID ERROR ";
  if (action != null) {
     msg += "caused by action '" + action + "', ";
  }
  msg += "Message: " + message;
  console.error(msg);
}

window.addEventListener("DOMContentLoaded", function() {
    try {
         var head = document.getElementsByTagName('head')[0];
         var js = document.createElement('Script');
         js.setAttribute('type', 'text/javascript');
         js.setAttribute('src', 'mraid.js');
         head.appendChild(js);
    } catch (e) {
        console.log("Error injecting mraid.js");
    }
    console.log('DOM Loaded');

    checkMRAID();
});
</script>
</html>

该代码以最简单的方式概述了如何与 MRAID API 进行交互。作为广告开发人员,您需要做的第一件事是通过将 mraid.js 脚本添加到您的广告标签来表明您是 MRAID 广告。通过侦听 DOMContentLoaded 事件可以做到这一点,因为这将在 DOM load 事件之前触发。尽快将这些信息提交给 SDK 是至关重要的,因为这是你与 MRAID 广告合作的唯一标志。如果您没有能力监听和处理 DOM 事件,那么您的广告脚本标记应该通过编写

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 注意Chrome、Firefox、Opera、Safari、IE9+都支持 DomContentLoaded。如果你的目标是 IE8,那么如果使用 jQuery,一定要使用 onload 或 DOM ready。

回到代码:接下来,通过在 checkMRAID()方法中添加一个事件侦听器来侦听 MRAID 就绪事件;。有时,事件在您可以调用侦听器来处理它之前就触发了,所以在这种情况下,您可以假设 MRAID 存在并被加载,并且可以安全地调用 init();。在 init 中,您删除事件监听器,检查 SDK 支持的 MRAID 版本,并检查您的放置类型。这些信息对于广告开发人员来说非常重要,如果早期版本的 MRAID API 不支持某些功能,他们可以调整广告体验。您还可以通过将宽度设置为 320,高度设置为 480 来设置您的扩展属性,并告诉 SDK 您正在使用自己的自定义关闭按钮,这样您就不需要在扩展时让 SDK 为您提供一个按钮。最后,为 MRAID 上的错误以及广告上的状态变化添加两个事件侦听器。最后,当 ad 调用 expandMRAID()和 closeMRAID() 时,可以调用 mraid.expand()和 mraid.close()方法来分别指示应用 ad 正在打开和关闭,这个函数应该暂停应用环境中的任何内容。

这个例子相当简单,但是就语法而言,可能需要一些时间来适应。MRAID 并没有就此结束;如果 creative 或 SDK 需要,还可以添加更多内容,包括保存图片、播放视频,甚至将提醒保存到移动设备的日历应用的方法。在 API 的 2.0 版本中,开放这些功能集,这对那些标准尚未完全确定并在 HTML5 或其他规范中采用的广告开发人员来说有很大的好处。也就是说,MRAID 并不打算与 HTML5 和 DOM APIs 或浏览器的新功能发生冲突。它充当广告和应用之间的通信层,并在需要时为广告创意提供特征检测,并允许广告适度降级。IAB 对 MRAID 2.0 的描述如下:

MRAID v.2 提供了一种标准的方式来查询富媒体 SDK 的某些设备功能,提供了视频创意的一致处理,并解决了 HTML5 目前没有很好地实现的两个原生设备功能:向设备日历添加条目和在设备照片卷中存储图像。

MRAID 是任何开发广告创意应用的人的福音,如果你发现一个应用不支持它,但提供广告,我强烈建议联系开发者,让他们采用它。事实上,非常努力地追求它;你将为他们、你自己以及将来需要开展活动的所有人提供服务。有关 MRAID 文档的更多信息,请访问 http://iab.net/mraid。

测试

在应用广告的世界里,没有什么比在设备上测试创意 更好的了。然而,在许多情况下,这与实际情况相去甚远。应用的发布者和内容所有者通常没有能力允许每个广告开发者访问他们应用的“测试版本”,要么是因为他们不知道如何这样做,要么是因为他们已经达到了他们可以分发的设备的极限。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 注意一个名为 TestFlightApp(testflightapp.com)的优秀应用测试服务可以帮助解决这个问题。

不管是什么情况,只要知道大多数时候获得发行商应用的测试版本是一种奢侈,所以调试你的广告代码可能是一个巨大的挑战。这里的问题是,在应用中的设备上进行测试可以提供最准确的结果,就像在多个浏览器中测试桌面活动一样。回想一下,当出版商提供测试页面时,广告服务器可以将他们的广告标签传输到一个与广告发布当天的真实环境非常相似的环境中。这是同样的概念,只是更难得到!

总是在一开始就询问与你合作的发行商和/或应用提供商他们是否能支持这一点,如果不能,他们还能以什么方式支持测试。了解他们是否可以提供他们的应用版本,这样你就可以运行你的广告,而不只是在浏览器中测试或相信别人的话。就我个人而言,我喜欢把我的广告测试分成以下四层。我总是试着射第一个球,但是有时候由于前面提到的各种原因,第一个球还是遥不可及。

  1. 在要运行的设备上使用应用的测试版本。
  2. 在要运行的设备上使用本机 web 浏览器进行测试。
  3. 使用要运行的设备的设备模拟器进行测试。
  4. 使用与移动 web 浏览器类似的渲染引擎的桌面浏览器,如 Webkit for Mobile Safari。

在 MRAID 的情况下,你可以在位于 http://webtester.mraid.org 的 MRAID 网络测试器中查看符合要求的广告,但是你也可以下载源代码并在你自己的域名上运行你自己的网络测试器。在那里,您将能够使用 MRAID API 模拟一个应用环境,并验证您的广告功能是否正常工作。

我想你会同意测试对于应用内广告来说是一个挑战,但是我预测随着时间的推移,随着更多的广告投入进入这个市场,这将变得更加容易。事实上,苹果的 iOS 6 和 Mac OS X Safari 允许通过桌面 Safari 使用 Safari 的开发工具在 iPhones 和 iPads 等设备上进行测试和检查。设计人员和开发人员现在可以在实际设备上实时查看他们的应用、web 内容和广告。

最终,在应用内的设备上进行测试是最理想的。但是,如果你需要满足于你可以访问的东西,使用 iOS、Android 和其他移动操作系统的模拟器,如果你需要,开车到你最近的电子商店,在地板模型上测试(说真的,我已经这样做了)。请记住,今天是平板电脑和手机,但接下来将是电视和其他电器和汽车。我们不能指望拥有并测试每一台冰箱,不是吗?争取从发行商那里获得测试应用,特别是如果你计划与他们一起做不止一次的活动。当你这样做的时候,构建、测试和调试将会顺利得多,如果你是一个应用开发者或发布者,使用像 TestFlightApp(testflightapp.com)这样的工具,它允许你通过空中(OTA)将你的应用传递给不同的团队成员。如果您的生产和开发团队遍布全球,这尤其有用!

MRAID 收养〔??〕〔??〕

MRAID 在某些方面仍然是相当新的,但它有望成为应用内部广告工作的标准。出版商需要一段时间来采用新的做法,但 MRAID 的支持是对行业的巨大推动,甚至是 IAB 的更大推动。在我写这篇文章的时候,IAB 正在为 MRAID 的未来版本进行许多测试和讨论,并向出版商和广告服务器发布认证标签,声明他们符合 MRAID 标准。虽然我个人希望他们能更好地监管这一点,所以出版商和广告服务器必须证明他们是 MRAID 兼容的,我想这将做他们声明他们是。如果他们不在,我们随时可以叫他们出来。

事实是,如果你有一个活动,要求你进入一个应用,因为它是在媒体购买中概述的,首先要确保出版商的 SDK 是 MRAID 兼容的。第二,进行一次试飞,以确保在进行一场真正的战役之前,一切都解决了。这将允许你轻松地跨多个发行商和应用进行伸缩,并且确信你的广告将在任何和所有支持该 API 的应用中正确运行。在这个空间中不再需要处理 SDK 碎片。我们都知道开发者有更大的事情要担心,尤其是在行业其他领域的分裂。如果你确实遇到了一个问题,一个出版商或应用声称它符合 MRAID 标准,但你的测试证明不是这样,告诉 IAB,以便它可以强制遵守(iab.net/guidelines/508676/compliance/2153679)。再说一次,这是为了整个行业的改善,而不是指责。

创意特色

在应用环境中工作允许 ads 与设备和本机设备功能 有更深入的整合。你可以拥有比典型的移动网络广告更丰富的功能。创意可以使用诸如检测网络连接、设备硬件和特殊文件访问等功能来添加到日历或相册中,正如您刚刚了解到的那样。当你构思下一个广告活动时,这些都应该被考虑在内,因为创意可以将所有这些惊人的功能考虑在内,并真正让用户惊叹。确保为创造性的头脑风暴会议带来合适的开发人员和技术人员。他们将能够在任何进展发生之前通知你某件事是不可能的。

摘要

这一章讲述了很多关于移动应用的内容,包括作为其中一部分的前景和盈利能力。此外,它还覆盖了各种移动设备应用中的广告的广阔世界。具体来说,我介绍了应用 SDK 的复杂世界,以及它们在应用环境中交付尖端富媒体的不可或缺的角色,以及它与移动 web 环境的不同之处。我回顾了 SDK 的分散角色,以及像 MRAID 这样的技术如何从应用开发人员和广告开发人员的角度来缓解这种分散。我讨论了 SDK 之间的一些细微差别,甚至回顾了一些代码示例,因此您可以在今天的活动中使用它们。我强调确保应用符合 MRAID 标准是很重要的,因为这一标准将使每个人的生活更加轻松。

在下一章中,我将讨论如何让广告离线,并在用户恢复网络连接时仍然进行报告。移动是一个很难成功导航的世界,但是了解基础知识将有助于你进入下一章。第十章见!

十、离线存储,跟踪、调试和优化

本章重点介绍移动和平板设备上日益重要的广告离线支持、强制跟踪,以及在浏览器和设备上调试的繁琐且通常非常耗时的过程。离线支持正成为许多网络应用的一项要求,广告也在迅速跟进。在这一章中,我将回顾如何处理离线事件,检测用户何时恢复在线,甚至讨论当用户网络连接不良时检测的 API。我将介绍如何使用 HTML5 的 AppCache API 将素材缓存到客户端浏览器和设备。我还将讨论通过跟踪像素和 JavaScript 来跟踪用户在广告中的交互,我将使用这些方法来处理跟踪调用,并使用 HTML5 的 API 在客户端数据库中存储调用。此外,我将讨论 IndexDB API 和 WebSQL API 之间的差异和浏览器支持。我还将讨论 Lawnchair JS 等 API,以及如何处理跨浏览器存储和缓存,以及如何在用户离线时启动跟踪调用。最后,我将详细介绍桌面浏览器和移动设备上的调试和优化。太多了,我们开始吧。

离线支持

从我记事起,我就一直从网络接入的角度来认识网络。从过去开始,我们有拨号调制解调器,然后是 DSL,然后是电缆线路,然后是今天的光纤。然而,在当今世界,我们还必须关注 2G、3G 甚至 4G LTE 连接等无线蜂窝网络,以及智能手机、电子阅读器和平板电脑等越来越多的设备是如何移动的。随着这些设备能够进入典型计算机不能进入的领域,如飞机、火车和汽车,网络连接可以来来去去,迅速而突然。幸运的是,开发人员可以使用浏览器的一个有用的新功能来检测用户是否可以访问网络。清单 10-1 概述了如何在兼容的浏览器中检测这一点。

清单 10-1 。 检测离线示例

<!DOCTYPE HTML>
<html>
<head>
<script>
function networkIndicator() {
document.getElementById('status').textContent = navigator.onLine ? 'online' : 'offline';
}
</script>
</head>
<body onload="networkIndicator()" ononline=" networkIndicator ()" onoffline=" networkIndicator ()">
<p>The network is: <span id="status"></span></p>
</body>
</html>

从前面的代码中,您可以看到我正在创建一个名为 networkIndicator 的函数,它会将 status 元素中的文本更新为 online 或 offline。然后在 body 元素的 onload 方法上,我调用了 ononline 和 onoffline 处理程序上的 networkIndicator 函数。这种简单的检测可以确定是否有网络连接。另外,前面的代码,当用户的网络访问变为连接或断开时,它还会调度下面这些你可以通过 JavaScript 处理的事件:

<script>
window.addEventListener("offline", function(e) {
        alert("offline");
});

window.addEventListener("online", function(e) {
    alert("online");
});
</script>

检查浏览器的 navigator.onLine 属性并在没有网络连接时提供替代体验是任何 HTML5 web 应用的必备功能,随着更多的广告进入 web 标准世界,您需要为需要它的出版商考虑这一点。就个人而言,将线下支持纳入品牌活动是最有意义的,因为游戏、视频或某种形式的重度用户互动是活动成功的最重要因素。对直接回应广告提供离线支持可能不是最有意义的,因为如果用户无法连接到任何网络,他们将无法点击/点击目的地和登录页面。然而,将游戏的元素缓存到设备或者甚至更小的预告视频以供离线使用允许用户在广告体验中进行交互并花费宝贵的时间。当品牌或广告商在活动结束后重新获得联系进行分析时,所有这些都可以被跟踪。基本上,如果用户有网络接入,你可以为他们提供完整的体验;例如,它可以是一个功能丰富的游戏或一个长篇视频广告。此外,你可以将重要的甚至替代的素材缓存到用户的浏览器中,这样当他们离线时,仍然可以在某种程度上与广告进行交互。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 注意出版商可能会要求不缓存任何内容供离线使用,或者对离线内容进行某些 k 权重限制。在开发广告之前,请咨询您的出版商或应用开发商。

广告中的离线支持绝不是标准做法。事实上,整个行业都在朝着一个坚实的标准努力,因为在检查可靠的连接状态时,使用 navigator.onLine 存在漏洞。例如,如果您的 ISP 关闭,但您的无线路由器启动并运行,会发生什么情况?浏览器可能会说用户在线,但实际上他们并不在线。更好的测试方法是通过 XMLHttpRequest (Ajax request )从服务器请求一个小素材来进行小检查,这样对最终用户来说是透明的,他们不会遇到任何带宽瓶颈,也不会刷新页面。使用清单 10-2 中显示的代码,您可以自信地识别用户是否连接。

清单 10-2 。 使用 Ajax 检测离线示例

<script>
function testConnection (fileToPing) {
  var xhr;
  if (window.XMLHttpRequest) {
    xhr = new XMLHttpRequest();
  } else {
    //For IE6, IE5
    xhr = new ActiveXObject("Microsoft.XMLHTTP");
  }

  xhr.onreadystatechange=function() {
    if (xhr.readyState==4 && xhr.status==200) {
      console.log("Online")
    } else {
      console.log("Offline")
    }
  }

  xhr.open("GET",fileToPing,true);
  xhr.send();
}

testConnection("http://www.yourdomain.org/1x1.gif");
</script>

清单 10-2 创建了一个名为 testConnection *,*的方法,该方法带有一个参数 fileToPing,这是一个你想要 Ping 的 URI 的字符串值,用来检查连接。该函数创建一个 XMLHttpRequest,并从服务器头检查状态是否为 200。如果是这样,您知道您对该素材的请求已经正确解析,因此用户已经连接。如果您没有从服务器获得 200 响应,您将确信用户离线。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 注意你必须在你的服务器上允许你想要请求的域名的访问控制允许来源。例如,使用 Access-Control-Allow-Origin:yourdomain.com或*,这将允许任何来源访问素材。

最好的情况是使用这两种技术来获得关于用户连接的最多信息。另外,一定要问清楚线下是否是发布者和/或广告主的强制要求。无论您使用 HTML5 还是从 API 调用到应用的 SDK 的特定“挂钩”,都要确保预先了解工作的全部范围。这是至关重要的信息,因此设计师和开发人员可以考虑以这种方式开发和设计广告的额外时间(如果有的话)。

有时文件会被缓存到浏览器/设备中,而您不希望它们被缓存。如果您为了验证指标而发出第三方或第四方跟踪电话,就可能出现这种情况。如果您不想允许缓存您的文件,您可以在向这些文件位置发出特定的 HTTP 请求时使用“cache-bust”方法。清单 10-3 展示了你将如何做来给第三方留下 1x1 的印象。

清单 10-3 。 缓存缉捕举例

<!DOCTYPE HTML>
<html>
<head>
<script>
function fireImpression () {
   var beacon = new Image ();
   beacon.src = "http://tracking.somedomain.com?r=" + cacheBust();
}
function cacheBust () {
   var num = Math.random();
   return num;
}
</script>
</head>
<body onload=fireImpression()>
</body>
</html>

使用前面的代码片段时,您创建了一个新的图像,并将该图像的源设置为您想要访问的 URI,但是您将一个缓存破坏方法连接到该字符串。这种破坏缓存的方法称为 cacheBust,它告诉浏览器生成一个随机数,并将其添加到查询字符串中的 r 参数中。这会产生类似于tracking.somedomain.com 的东西吗?r=0.123456 ,这种做法可以用于任何 HTTP 请求;请记住,缓存素材在大多数情况下是一件好事,比如不会改变的较重的 k-weight JavaScript 库、图像或 CSS 文件。然而,对于报告和分析,为了获得准确的结果,缓存破坏是相当强制性的。

当使用应用内时,一些 SDK 要求将广告缓存到设备上以供离线使用。例如,如果你要查看华尔街日报 iPad 应用,内容和广告会被缓存到设备中,这样用户就可以在离线模式下查看内容。如果用户要登上一架没有连接的飞机,这将非常有用。在这种情况下,当前的 SDK 提供商 AdMarvel 通过缓存文件将应用内容和所有广告缓存到设备中。清单 10-4 展示了如何使用 AdMarvel SDK 实现这一点。

清单 10-4 。 AdMarvel 缓存文件示例

ADMARVEL-CACHE
assets/style.css       http://cdn.domain.com/assets/style.css
assets/script.js       http://cdn.domain.com/assets/script.js
assets/logo.png       http://cdn.domain.com/assets/logo.png

缓存文件保存为制表符分隔的。txt(纯文本)文件,通过相对和绝对位置(本地/远程)定位构成广告体验的所有素材,并与广告创意一起交付给 AdMarvel。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 注意每个 SDK 都有自己实现缓存广告素材的方式。请务必在活动开始前与他们核实。

网络连接 API

本节介绍网络连接 API ,它允许开发者查询用户当前使用的网络连接的强度和类型。在撰写本文时,该 API 目前还不被任何现代浏览器支持,但是它的 API 文档正在修订中,当这一新兴标准在现代浏览器中可用时,它将提供许多有用的特性。目前的 API 允许开发人员检测用户是否在使用以太网、WiFi、2G、3G、4G、无或未知连接。将这类信息与 Navigator.onLine 和 Ajax 测试结合起来,开发人员可以将他们的广告体验用于复杂的离线使用。如果您不能等到规范最终确定或浏览器将它实现到他们的架构中,您可以通过 SDK 从应用内广告中利用这一点。事实上,在 MRAID,广告开发人员和设计人员可以通过调用 getNetwork *方法向 MRAID 兼容的 SDK 查询有关用户连接的信息。*此外,当网络连接发生变化时,他们可以为 networkChange 事件添加一个事件监听器。目前,MRAID 可能的连接类型有离线、WiFi、手机和未知。理想情况下,我们会看到这些 API 很快成形,并立即实现,这样采用就会很快。只有这样,您才能提供准确的网络连接检测,并提供丰富的离线体验。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 注意如果您的广告需要离线可用性,请确保删除 tap 周围的任何 CTA,因为离线查看广告时将没有网络,因此用户将无法查看页面。

应用缓存

在这一节中,我将介绍离线 web 应用规范以及如何使用应用缓存。本节面向希望为其 web 应用提供离线支持的出版商和内容所有者。在 HTML5 中,通过创建一个简单的清单文件来支持应用缓存,该文件列出了应用脱机使用的素材。这些素材是需要存储到用户浏览器的文件,以便在没有任何互联网访问的情况下正确呈现。在我们深入探讨之前,请记住,将所有素材缓存到用户的浏览器可能会导致很长的缓存时间以及臃肿的清单文档,因此请明智地选择存储。

当用户在无法访问网络的情况下查看文档时,浏览器会切换到使用本地缓存的资源。因此,理论上,假设应用缓存正确地将文件存储到了设备上,用户应该能够在地铁或没有飞行 WiFi 的飞机上完成与游戏的交互或观看视频。有了强大的浏览器支持,特别是在移动领域,这是你可以立即开始利用的东西。图 10-1 概述了截至 2012 年 11 月对应用缓存的巨大支持。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 10-1。演示浏览器对 HTML5 应用缓存的支持(来源:caniuse.com)

使用 HTML5 应用缓存,出版商可以提供更快、响应更快的 web 应用,这对于最终用户来说是一种更好的用户体验。此外,如果你是 Chrome 用户,我建议使用 chrome://appcache-internals,它可以帮助检测哪些域正在你的浏览器中存储素材。

应用缓存示例

因为我刚刚介绍了为什么您应该利用离线素材缓存,所以我将展示如何将理论付诸实践。虽然 HTML5 AppCache API 通常用于缓存 web 应用中的特定素材,但您也可以使用类似的缓存机制来缓存离线广告内容。当然,这肯定意味着如果你在发布端,这将增加你的工作量,因为你需要在每次新闻广告更新时更新缓存清单。当出版商的内容(如杂志、报纸和其他完全缓存在用户设备上的内容)需要离线查看时,这一点变得越来越重要。查看以下代码片段,了解如何使用 AppCache 。在 HTML 标记中,添加对。通过编写以下内容来创建 appcache 文件:

<!DOCTYPE HTML>
<html manifest="cache.appcache">
. . .
</html>

在前面的示例中,您向名为 manifest 的 HTML 文件中的 HTML 节点添加了一个属性,并将该属性设置为 cache.appcache ,它是与 HTML 文件位于同一目录中的清单文件。

接下来,让我们看看如何构建清单文件。您可以使用下面的示例清单结构来构建您的离线广告,但是请注意,根据发布者和广告内容的不同,这些素材需要针对您自己的特定用例进行更改。在构建清单缓存文件之前要做的第一件事是设置您的服务器接受 MIME 类型的. appcache。appcache 到我的。我的服务器根目录下的 htaccess 文件。请记住,一些服务器可能没有这个文件,或者它可能是隐藏的,所以一定要查看隐藏文件来找到它。否则,就创建一个。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 了解更多信息。htaccess,我推荐去htaccesstools.com看看。

一旦您的服务器被配置为接受 appcache 文件类型,您就可以用您的缓存素材构建一个清单文本文件,并将其保存为 yourfile.appcache。

清单 10-5 。 构建一个 HTML5 AppCache 文件

CACHE MANIFEST
# 2012-12-13:v1 – Keep the version to purge the cache when updates are needed

# Explicitly cached entries
CACHE:
index.html
css/style.css
ad/adstyle.css
js/script.js
ad/adscript.js
ad/bg.jpg
img/button.png
img/bg.jpg
fonts/webfont.otf
fonts/webfont.ttf
fonts/webfont.woff
fonts/webfont.svg
media/audio.mp3
media/video.mp4
media/video.webm

# offline.html will be served if the user is offline and request new "non-cached" assetsFALLBACK:
index.html offline.html

# Resources that require the user to be online.
NETWORK:
submit.aspx
http://api.twitter.com
etc. . .

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 注意您可以通过以#开始一行来向清单文件添加注释。此外,如果一项素材下载失败,整个缓存都会失败。

让我们回顾一下清单。您要做的第一件事是定义缓存清单,并设置一个带有上次更新日期和版本号 1 的注释。你要做的第二件事是,通过编写 ad/style.css、ad/adscript.js 和 ad/bg.jpg,列出你需要缓存到用户浏览器供离线使用的所有素材和文件,包括广告的素材,记住,这不需要是你的所有素材,只要足以提供可接受的离线体验即可。在这个例子中,我已经包括了 CSS、JS、图像、字体、媒体和广告素材,但是这很可能是多余的,这取决于您的 web 应用和广告的创意需求。此外,要小心你在广告中缓存的内容。一旦 JavaScript 文件等素材被缓存,即使您在服务器上更改文件,浏览器也将继续使用缓存的版本。确保浏览器更新缓存素材的唯一方法是更改。appcache 文件,这就是为什么要通过编写在注释部分添加日期和版本。# 2012-12-13:v1。清单文件中的下一步是在清单的 FALLBACK 部分下为您的 index.html 文件提供一个备用 offline.html 文件,当用户离线并试图访问未缓存的信息时,将会提供该文件。在用户访问他们看不到的信息时,这是一个很好的选择;在这种情况下,他们将获得默认的缓存素材,而不是他们在线时没有缓存的素材。

出版商可能会从 HTML5 的 AppCache API 中看到真正的好处,因为他们可以有效地为他们的客户和访问者创建非常丰富的离线体验,同时仍然为他们提供用户想要的内容。广告或多或少会找到自己的方式来为用户缓存素材,但在走上任何特定的道路之前,一定要与你的出版商、广告服务器和代理商进行对话。

既然已经在 HTML 文档中设置并分配了缓存文件,让我们使用一些 JavaScript 来检测素材的加载和缓存(参见清单 10-6 )。

清单 10-6 。 HTML5 AppCache JavaScript 示例

<script>
var cache = window.applicationCache;

cache.addEventListener('cached', handleCacheEvent, false);
cache.addEventListener('checking', handleCacheEvent, false);
cache.addEventListener('downloading', handleCacheEvent, false);
cache.addEventListener('error', handleCacheError, false);//Good to use if the manifest is moved or if the user is offline
cache.addEventListener('noupdate', handleCacheEvent, false);
cache.addEventListener('obsolete', handleCacheEvent, false);
cache.addEventListener('progress', handleCacheEvent, false);

// When a new manifest is downloaded, swap the new cache assets and reload.
cache.addEventListener('updateready', reloadAssets, false);

function reloadAssets (){
     if (cache.status == cache.UPDATEREADY) {
          cache.swapCache();
          if (confirm('A new version is available')) {
               window.location.reload();
          }
     }
};

function handleCacheEvent () {
. . .
}
</script>

使用前面的 JavaScript,您可以将事件侦听器添加到 applicationCache,并在素材处于缓存过程的不同阶段时、素材正在下载时、素材准备就绪时以及其他事件中进行处理。当确定用户是否有最新和最大的素材可供脱机使用时,以及当对您的缓存清单文件进行常规调试时,这非常有用。

因此,您可能想知道为什么要在本地缓存素材。浏览器没有原生缓存吗?是的,确实如此,但这通常是不可靠的,因为用户和浏览器通常会在缓存池填满太多后清除缓存,或者这可能是默认的浏览器设置,在每次浏览器会话后清除缓存。

缓存资源可以创建更快的 web 内容,无论网络连接如何,这都是一种全面的改进。当你进入动态广告时,这可能是非常有益的,用户可能会在整个活动周期中看到各种各样的广告版本。既然只有广告的某些部分是动态的(文本、图片等等),为什么不在随后的视图中下拉动态素材,让其他素材保持不变呢?这将允许更快的加载时间,并且能够只从服务器中提取您需要的素材,从而减少需要发生的请求的数量。今天,这些做法正在许多网络应用中使用,包括谷歌的 iOS 和 Android 版 Gmail。一篇关于缓存及其对网络影响的非常好的文章可以在www.stevesouders.com/blog/2012/10/11/cache-is-king找到

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 关于 AppCache 的更多信息和事实,请访问appcachefacts . info

跟踪

追踪广告是任何活动的关键部分。分析团队渴望广告服务公司收集的指标,以便他们可以更好地调整他们的媒体支出,并更好地教育他们的客户在他们的在线广告活动中什么是有效的,什么是无效的。要做到这一点,跟踪必须贯穿整个广告,这样当用户与广告内容互动时,报告公司可以了解互动的发生。跟踪需求的一个重要主题是当网络访问不存在时跟踪用户的能力。这种离线跟踪在移动设备中很重要,用户更倾向于在离线情况下与手机和平板电脑应用进行交互。

正如你在本书的前几节中所知道的,只有当用户访问了 cookie 丢弃域或者将他们的浏览器设置切换为全部接受时,移动苹果设备上的 cookie 丢弃才被接受。虽然这消除了广告客户寻求瞄准的很大一部分市场,但其他浏览器在 iOS 上越来越受欢迎,如谷歌的 Chrome 浏览器,它默认接受 cookies,而不管域如何,在撰写本文时,iOS 版 Chrome 大约有 20,000 个用户评级。虽然不是安装的真实衡量标准,但这仍然是一个有希望的数字,但由于没有能力使 Chrome 成为用户的默认移动网络浏览器(除非你“越狱”你的 iOS 设备),你肯定会看到比 Chrome 更多的移动 Safari 流量。移动领域的其他浏览器,如 Opera Mini,处理追踪的方式有所不同。对于像非洲这样的发展中国家的很大一部分市场份额来说,有线网络很少,大多数是带有 Opera Mini 的电话。然而,对于 Opera Mini,JavaScript 在默认情况下是不打开的,或者是不存在的,所以在这些场景中,唯一的跟踪形式称为像素跟踪 ,或者使用 1x1 图像,其中用户单击 HTML 标记中的标签,请求通过重定向 URL。然而,在大多数情况下,JavaScript 是最常见的,许多分析平台如谷歌的分析使用清单 10-7 所示的跟踪方法。

清单 10-7 。 谷歌分析追踪示例

<script type="text/javascript">
  var _gaq = _gaq || [];
  _gaq.push(['_setAccount', 'UA-25177661-1']);
  _gaq.push(['_trackPageview']);

  (function() {
    var ga = document.createElement('script');
    ga.type = 'text/javascript'; ga.async = true;
    ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
    var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
  })();
</script>

现在,在基于 HTML 的广告中,你可以使用网络分析平台,如谷歌概述的平台,来处理你的指标。但是,如果浏览器中禁用了 JavaScript,那么基于 JavaScript 的跟踪也会被禁用。一个好的解决方法是使用 imagebeacon,这是一个 ping 服务器的 1x1 GIF 图像,通常带有特定的查询参数,指示会话 id 或创意 id,以及活动类型和一个随机数来缓存 bust。不管怎样,最好是了解你的受众是谁。如果你的目标是一堆移动设备,请记住,一些移动浏览器在一些手机上默认没有 JavaScript,例如黑莓的 OS5 和更老的手机以及大多数诺基亚功能手机。

存储和发射离线跟踪

虽然线下广告跟踪没有标准定义,但需要一个标准,理想情况下,通过实践和采用,我们将在未来的活动中有一个干净的线下实现方式。Crisp Media 的开发副总裁兼 ORMMA initiative 的联合创始人 Nathan Carver 声明如下:

“这确实在一定程度上取决于广告。如果是直接回应,比如说,那么线下就没有意义了。真的只有品牌广告受益于线下。最终,这是 SDK 目前的差异化空间。存储转发或保管/分享技术可能真的有所帮助,但目前还没有关于线下市场的定义。”

内森·卡弗

首先,用户在网上与广告互动;在整个交互过程中,网络连接变得很差,用户不可避免地会离线一会儿。由于广告已经被缓存到用户的设备(使用广告服务设备检测),用户不会注意到他们实际上是离线的,因为广告的所有功能仍然完好无损。这里重要的变化是广告中的每一次互动都是可追踪的;如果用户离线,这些跟踪活动将无法返回到服务器。也就是说,你需要在客户端捕捉这些互动,以免它们永远消失,失去宝贵的品牌洞察力。通过使用 HTML5 和各种其他 API,您可以利用各种新技术来实现这一点,包括本地存储/会话存储,甚至客户端数据库,如 WebSQL 和 IndexedDB,您将在下面的部分中了解到一些内容。让我们看看如何使用 HTML5 的本地存储技术来处理清单 10-8 中的离线点击跟踪。

**清单 10-8 。local storage 离线点击跟踪示例

<script>
var NetworkAccess = navigator.onLine;
var trackingCalls = {
    "clicks" : [{
        "name": "clickButton1",
        "online": "1023-online",
    }, {
        "name": "clickButton2",
        "online": "1024-online",
    }]
}

function trackClick(name) {
    if (!NetworkAccess) {
        //No network - clicks won't fire
        return false;
    } else {
        var trackingID;
        var clickName;
    }

    for (var n = 0; n < trackingCalls.clicks.length; n++) {
        if (name == trackingCalls.clicks[n].name) {
            clickName = trackingCalls.clicks[n].name;
            trackingID = trackingCalls.clicks[n].online;
        }
    }

    if (trackingID){
        location.href = "http://clicks.someurl.com?clickName=" + clickName + "&trackingID=" 
+ trackingID + "&r=" + cacheBust();
    }
}

function cacheBust () {
    var num = Math.random();
    return num;
}

function buttonClick (event) {
    var type = event.target.attributes.value.value;
    switch (type) {
        case "buttonOne" :
            trackClick("clickButton1");
            break;
        case "buttonTwo" :
            trackClick("clickButton2");
            break;
    }
    console.log(type)
}

function AdInit () {
    console.log("AdInit : NetworkAccess " + NetworkAccess)
    document.removeEventListener("DOMContentLoaded", AdInit);

    //set up Ad UI here

    document.getElementById('buttonOne').addEventListener('click', buttonClick, false);
    document.getElementById('buttonTwo').addEventListener('click', buttonClick, false);
}

document.addEventListener("DOMContentLoaded", AdInit, false);
</script>

让我们回顾一下这段代码。您要做的第一件事是通过检查 NetworkAccess 和重要的 trackingCalls JavaScript 对象在脚本顶部设置您的跟踪变量,该对象存储所有在线使用的点击。接下来,在脚本的底部,您开始监听您的 DOMContentLoaded 事件,并启动 adInit 函数,这将启动程序;那里没什么新东西。接下来,如果用户在广告环境中单击 buttonOne 或 buttonTwo,它将通过一个名为 buttonClick 的函数,该函数将接受事件参数并执行一个 switch/case 来确定哪个按钮被单击。根据触发的事件,您将调用函数 trackClick 并为按钮传入字符串值;在这种情况下,它可以是 track click(" click button 1 “);或者 track click(” click button 2 ");。现在,如果您使用 trackClick 功能,您会注意到您做的第一件事是检测用户是否可以访问网络。如果没有,您只需将用户从函数中返回。但是,如果它们这样做了,您需要设置两个新的变量 trackingID 和 clickName ,这两个变量将存放您想要保存的跟踪值。当 for 循环遍历 JavaScript 对象中定义的所有跟踪点击时,您可以根据用户的操作来跟踪用户并将其发送到适当的 URL(如果已连接)。

既然您已经了解了如何处理离线点击,那么让我们从广告体验的角度来看一下用户活动。同样,这是你想报道的广告的局部内容,不会将用户从广告体验中引开。理解互动是很重要的,比如滑动、触摸、视频播放、游戏,以及其他对广告商的品牌认知活动很重要的东西。看看清单 10-9 中修改后的代码。

清单 10-9 。 LocalStorage 离线活动跟踪示例

<script>
var NetworkAccess = navigator.onLine;
var trackingCalls = {
    'pings': [{
        'name': 'touchstart',
        'online': '1011-online',
        'offline': '1011-offline'
    }, {
        'name': 'touchmove',
        'online': '1012-online',
        'offline': '1012-offline'
    }]
}

function trackPing (name) {
    var activityName;
    var onlineTrackingID;
    var offlineTrackingID;

    for (var n = 0; n < trackingCalls.pings.length; n++) {
        if (name == trackingCalls.pings[n].name) {
            activityName = trackingCalls.pings[n].name;
            onlineTrackingID = trackingCalls.pings[n].online;
            offlineTrackingID = trackingCalls.pings[n].offline;
        }
    }

    if (NetworkAccess) {
        fire('http://tracking.someurl.com?trackingName=' + activityName + '&trackingID=' + onlineTrackingID + '&r=' + cacheBust(), false);
    } else {
        var t = new Date().getTime();
        var m = new Date().getMonth()
        var d = new Date().getDate();
        var y = new Date().getFullYear();
        var timeStampedName = activityName+t+m+d+y;
        //No network - storing offline tracking
        storeOffline(timeStampedName, offlineTrackingID);
    }
}

function storeOffline (name, id) {
    //store client side and add listeners for network events
    console.log('Storing Offline : ' + name + ' + ' + id)
    localStorage.setItem(name, id);
}

 //on reconnect fire off all the cached pings
function checkOfflineStorage () {
    if(NetworkAccess) {
        if (localStorage.length >= 1) {
            for (var i = 0; i < localStorage.length; i++) {
                var key = localStorage.key(i);
                var value = localStorage[key];
                var offlineCall = 'http://tracking.someurl.com?trackingID=' + value + '&r=' + cacheBust();
                fire(offlineCall, true);
            }
        } else {
            console.log('No offline metrics stored')
        }
    }
    console.log('NetworkAccess ' + NetworkAccess)
}

//Tracking Utils
function fire(url, clear) {
    var trackingImg;
    if (clear === true) {
        trackingImg = new Image ().src = url;
        console.log(trackingImg);
        setTimeout(clearStorage, 3000);
    } else {
        trackingImg = new Image ().src = url;
    }
}

function clearStorage() {
    console.log('clearing storage');
    localStorage.clear();
}

function cacheBust () {
    var num = Math.random();
    return num;
}

function userAction (event) {
    var type = event.type;
    switch (type) {
        case 'touchstart' :
            trackPing('touchstart');
            break;
        case 'touchmove' :
            trackPing('touchmove');
            break;
    }
    console.log(type)
}

function AdInit () {
    console.log('AdInit')
    document.removeEventListener('DOMContentLoaded', AdInit);

    //set up Ad UI here
    window.addEventListener('touchstart', userAction, false);
    window.addEventListener('touchmove', userAction, false);

    checkOfflineStorage();
}

window.addEventListener('online', checkOfflineStorage);
window.addEventListener('offline', checkOfflineStorage);

document.addEventListener('DOMContentLoaded', AdInit, false);
</script>

让我们回顾一下代码示例。同样,它在设置上与点击跟踪示例非常相似,但是现在一旦您进入 adInit 函数,您就可以通过调用 window . addevent listener(" online ",checkOfflineStorage,false)为 ad 环境设置您的触摸事件侦听器,并为在线/离线状态设置一个事件侦听器;。接下来,调用 checkOfflineStorage 函数来确定是否有任何存储的离线活动。在 checkOfflineStorage 中,首先检查用户是否有网络连接,以及 localStorage 对象中是否存储了项目。如果有网络但没有存储,您只需通过编写 console.log(‘没有存储离线指标’)来登录控制台。但是,如果有项目存储在 localStorage 中,您可以通过获取它们的键/值并将其传递给一个名为 fire *的函数来遍历它们。*现在,在 fire 函数中,通过编写 if (clear === true ),您检查是否需要在启动跟踪调用后清除存储。现在,您将创建图像对象,并将 URL 请求添加到跟踪服务器,方法是将该值设置为图像的 source 属性。最后,一旦您启动了所有的调用,您就可以设置一个超时来调用函数 clearStorage,这将清除用户浏览器中所有的 localStorage 跟踪调用。现在代码中有很多内容,所以我建议使用您最喜欢的文本编辑器,并在您最喜欢的浏览器的 web inspector 中检查所有日志。请记住,这种技术对于数字杂志和出版物变得越来越重要,因为它们的所有内容都被缓存到用户的设备上。通过 JavaScript 使用 HTML5 的离线检测,可以相应地处理度量;除了前面的 XMLHTTPRequest 方法,您还可以确保用户是否真正连接。

对于与 SDK 供应商(如 AdMarvel 或 Medialets)合作的移动人员来说,他们很有可能为您提供离线指标的缓存。作为一名广告设计师,你很可能只需要调用特定的 SDK 方法,SDK 会为你处理这些。除此之外,MRAID 工作组已经提出了包括实现离线跟踪的标准方法的想法,但现实是这个领域还太年轻,还不能标准化。让我们看看 MRAID API 文档中的引用:

能够在设备没有网络连接的情况下工作的富媒体广告需要能够存储并稍后转发关于用户如何以及何时与广告交互的指标。MRAID 然而,在测量方法和指标本身标准化之前(例如通过正在进行的 IAB/MMA/MRC 应用内广告测量指南项目),为 MRAID 增加测量功能还为时过早。MRAID 工作组期望这种能力将被评估并可能作为未来 3.0 版本的一部分添加到 MRAID 中。

MRAID 工作组

MRAID 的工作组有一个很好的方法,我认为在确定一个解决方案并将其称为标准之前,最好先看看所有提议的解决方案。会是 HTML5 和各种允许标准化离线跟踪的 JavaScript APIs 吗?或者它会是只涉及 SDK 的其他东西吗?或许两者都有?与此同时,客户会要求你这样做,这最终会成为在线广告领域的标准操作程序。现在,你必须拿出你自己的自制解决方案,就像之前概述的那样,或者你甚至可以看看轻量级的 JavaScript 库,比如 lawn chair(brian.io/lawnchair)来满足你的需要。

Lawnchair 似乎是客户机数据库存储的一个可能的答案,因为它通过 JavaScript 使用简单的名称/值对赋值,并通过 JSON 检索值。它还可以配备许多适配器,以便在一些浏览器不接受其他技术的情况下,优雅地切换到其他客户端存储技术。这意味着它将使用 blackberry-persistent-store、DOM storage、WebSQL 和 IndexDB,等等。Lawnchair 缓解了存储技术之间的碎片化,并为开发人员提供了一种节省价值的简单方法。另外,缩小后只有 6KB,压缩后更小。这非常有利于创建用户交互的离线档案,并最终在用户重新获得网络连接时迭代交互并启动用户活动。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 注意如果大多数用户与广告交互,并且从未重新获得网络访问权以将指标推送到报告服务器,则跟踪可能会偏离离线使用。应该向所有团队传达这永远不会是 100%准确的。

索引 b

在讨论离线缓存和离线指标的话题时,我不得不提到 HTML5 中一个新出现的 API,名为 IndexDB 。IndexDB 是一个 API,用于在客户端以非常结构化的方式存储大量数据。使用 IndexDB 通常意味着您有大量的数据要处理,并且比使用 sessionStorage 或 localStorage 的典型 DOM 存储要多得多,这可能会面临浏览器对存储到客户端的数据量的限制。虽然这两个 API 都为客户端浏览器提供了处理大量数据的好方法,但是当您处理非常大的数据池并且需要以结构化的方式大规模处理数据时,IndexDB 将是您的首选。由 Mozilla group 开发,使用这种精心制作的网络存储,你可能允许用户在广告体验中定制一个详细的载体,并在下次访问另一个网站的广告时从他们停止的地方继续。

IndexDB 现在是 HTML5 工作组正在研究的最新规范。根据 W3C 的说法,以前 WebSQL API 是离线存储大量数据的主要方式,但该规范已经停止发展。(然而,它仍然在一些浏览器中使用。)据说该行业在可预见的将来会向 IndexDB 过渡。 Origin ,或者说创建数据库的站点的域,作用于每个 IndexDB 数据库,这可能是处理广告离线数据的一个好的解决方案,但是要注意的是,它可能还不能在所有的浏览器中工作。请务必关注 http://caniuse.com/#feat=indexeddb 的以确定支持。

Web 检查器

可以说最流行的 web 开发工具是 Web Inspector ,它内置于所有现代浏览器中。如果你使用 Chrome、Opera、Firefox 或 IE 10,你只需右击你的浏览器窗口并选择 Inspect Element *。*这将在你的浏览器中打开 Web Inspector,并为你提供一系列工具,用于检查你的 DOM 中的元素,查看加载的脚本,分析网络流量,了解离线存储,以及实时执行命令。如果您使用的是 Safari,您需要首先进入浏览器偏好设置,并在菜单栏中启用开发菜单。启用后,您将能够像其他元素一样右键单击并检查元素。图 10-2 显示了在苹果的 Safari 浏览器中寻找什么。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 10-2。 Safari 的开发菜单设置

除了流行的 Web Inspector,还有一个名为 Firebug 的浏览器扩展,它本质上做类似的事情,并为开发人员提供类似的工具,用于在各种浏览器上调试 Web 内容。要了解更多关于 Firebug 的信息,请访问 http://getfirebug.com。Firefox 最近也更新了它的网页检查器,可以观看 3D 内容。如果您需要了解元素的堆叠顺序并确定某些元素是否位于其他元素之上,这将非常有用

开发工具

如果你曾经做过一段时间的开发人员,你就会知道有多少时间可以投入到代码调试的艺术和过程中。如果你是开发新手,相信我说的,“习惯于不工作的东西,并开始学习解决它们。”除了拥有正确的工具、工作流程和技术之外,耐心是调试中的一个关键特质。在这一节中,我将回顾一些非常棒的免费工具,以及一些惊人的技术,它们将在为多个平台和设备进行调试时为您带来竞争优势。

网络上有大量的开发者工具。只要谷歌一下任何网络开发工具,你就会看到很多结果。我最喜欢的几个在线工具是 js console(jsconsole.com)用于调试移动设备上的 JavaScript,JSBin(jsbin.com)用于快速模仿并与朋友和同事分享代码,js beautiier(jsbeautifier.org)用于干净地取消库和代码的混淆以提高可读性,remote tilt(remote-tilt.com)用于在原生设备之外处理动作事件。Remy Sharp 是 extra ordinaire 的开发者,他开发了除 JSBeautifer 之外的所有这些工具,我个人在调试广告内容时在无数的活动中使用过它们。其他非常有用的工具包括 DOM monster(mir.aculo.us/dom-monster)、y slow(yslow.org)和 page speed(developers.google.com/speed/pagespeed),所有这些工具都允许调试和优化你的网页内容。

我最喜欢的一个工具是 HTTP 监控工具。这些类型的工具捕获并记录浏览器中发生的所有 HTTP 流量。例如,如果您有一个发出许多 HTTP 请求并调用外部服务的广告,那么这个工具非常有价值,可以让您了解“幕后”到底发生了什么。其中一些工具是查理(Mac 版)(charlesproxy.com)和菲德勒(PC 版)(fiddler2.com/fiddler2),它们甚至可以代理到你的移动设备上,用于捕捉智能手机、平板电脑和电视上的网络流量。这些 HTTP 监控工具真正了不起的地方是能够验证跟踪、报告和重定向来自广告的呼叫。开展活动后,进行测试以确保报告的准确性至关重要。对于那些使用 Firefox 的人来说,还有一个免费的浏览器插件叫做 http fox(addons.mozilla.org/en-us/firefox/addon/httpfox),它本质上做的事情和 Charles and Fiddler 一样,但是直接在浏览器内部。另一个是 Firefox 插件 Live HTTP Headers(HTTP://addons . Mozilla . org/en-US/Firefox/addon/Live-HTTP-Headers),它允许用户在浏览时查看页面的 HTTP 标题。HTTP 监控对于移动调试非常有帮助,因为移动设备目前缺少本地开发工具。要使用 Charles 共享到您的设备,请查看以下步骤。

对于 iDevices ,连接到计算机和无线设备之间的共享网络,然后转到 iDevice 上的设置。在 HTTP Proxy 下,选择 Manual,并在 server spot 中输入您计算机的 IP 地址;然后输入任何未使用的端口,如 8888 。接下来,开始访问移动 Safari 或某个应用(任何有网络流量的东西),最终 Charles 会提示您,另一个服务正在请求使用这个网络作为代理。选择“允许”,并开始使用您的设备,同时在您的电脑上查看网络流量。

当您需要调试应用内部的广告时,如果您没有浏览器的本机功能(如控制台日志),那么在移动设备上调试可能会更成问题。在移动应用中进行调试时,您可以利用 HTTP 请求的能力来欺骗调用,使其成为跟踪语句,以了解您的 ad 代码内部发生了什么。一个很好的例子是创建一个虚拟图像文件,并将其来源分配给一个带有一些日志语句 URL 参数的假跟踪调用。下面的例子概述了我正在讨论的内容:

<script>
function adInit() {
        var traceImage = new Image();
        traceImage.src = "http://yourdomain.com?trace=statement";
}
</script>

现在,当调用函数 adInit 时,您将在 HTTP 监视器中看到一个对伪 URL 的请求,trace 的查询参数等于您想要输出的任何语句。在这种情况下,这可能是在广告体验中开始的功能,所以它可能看起来像下面的代码片段(和图 10-3 ):

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 10-3。网络监控查理斯(Mac)

<script>
function adInit() {
        var traceImage = new Image();
        traceImage.src = "http://yourdomain.com?trace=AD-STARTED";
}
</script>

从示例中可以看出,这在调试浏览器和移动设备中的网络流量时非常有用。使用这些技巧,开发人员可以深入了解他们的代码是如何执行的,即使他们不能在物理设备上测试。

移动开发工具

移动开发工具是一个正在成长的行业。这曾经是一个完全令人头痛的管理问题,因为工具不可用,而移动广告作为一项业务已经飞速发展,所以需求很大。Adobe Edge Inspect(html.adobe.com/edge/inspect)和 Weinre(pmuellr.github.com/weinre)等工具直接在你的台式机上为移动设备和平板电脑提供远程调试和开发。其他一些真正伟大的开发工具是在你的个人电脑上测试移动模拟器和仿真器的能力。这将使用苹果的 Xcode 和 Mac AppStore 上的 iOS 模拟器、谷歌的 Android 开发工具(developer.android.com/tools/index.html)、黑莓 10(developer.blackberry.com/platforms/bb10)、Windows Phone(microsoft.com/en-us/download/details.aspx?id=27570)和 Opera 的移动模拟器(opera.com/developer/tools/mobile)。这些工具中的每一个都提供了与您在设备上观看内容时所期望的非常相似的体验。然而,对设备本身进行测试是目前为止作为开发人员所能做的最好的测试。如我所说,如果你需要去你当地的电子商店测试一些广告,那就去做吧!

现在也有很多服务可以用来测试你的内容在各种设备上的表现和功能。一个这样的服务叫做 device anywhere(keynotedeviceanywhere.com),它有效地允许在任何特定设备上虚拟查看你的内容。你想知道你的广告在运行 iOS 3.1 的第一代苹果 iPad 上是什么样子的?它掩护你。运行 Android 2.3 的 HTC 怎么样?是的,那个也是!DeviceAnywhere 是一个很好的工具,可以利用它访问的设备,但在我看来,它仍然缺乏动手调试的经验。如果你是一个出版商,想在移动设备上测试你的网络内容,但手头的资源有限,那就去看看 Akamai 的 MobiTest(【http://mobitest.akamai.com/m/index.cgi】??)。该工具允许用户从不同的位置在不同的设备上测试页面内容,您甚至可以视频捕捉结果以与其他同事共享。再说一次,这些工具中的大多数都是你试图为像我这样的怀疑者测试的环境的虚拟窗口;你可能只需要在真实的东西上测试。

最佳化

在制作网页内容或广告时,优化是一个持续的过程。即使不是为了满足发布者的要求而提高性能,DOM 中的每一项添加内容或加载到广告中的任何附加素材最终都需要进行优化。此外,带宽是一种有限的资源,用户体验是首要的,所以一定要使用 Adobe 的 Photoshop 或 Fireworks 等程序使用适当的设置来压缩图像。如果你是一名 Mac 用户,可以使用名为 ImageOptim(imageoptim.com)和 image alpha(pngmini.com)的图像优化应用来优化透明的 PNG。

对于脚本方面的事情,请确保您通过自己的垃圾收集来完成清理工作;如果您有事件侦听器,请确保在处理完事件后删除它们。此外,确保在不需要动画循环或迭代过程时移除它们。像 setInterval 和 setTimeout 这样的计时器会变得很贵,很快就会变得很累,所以一定要在不使用时清除它们。

确保总是缩小基于文本的文件,如制作广告的 HTML、CSS 和 JavaScript,并保留一份更详细的版本,以便回去进行编辑,这样你就不必处理缩小的版本。在缩小的同时,确保尽可能使用 GZIP 压缩。通过对基于文本的文件进行 gzip 压缩,您创建了一个. gz 版本的文件,它比单独的缩小版本要小得多。通过 GZIP 压缩允许最小的文件传输大小,这将最小化带宽限制,并提供整体更快的网络体验。只要确保你的托管服务器或 CDN 有适当的配置来提供 GZIP 文件。如果请求浏览器的用户不能在呈现文件之前解压缩或解压文件,则用户将只得到缩小版本的资源,尽管现在大多数浏览器都支持压缩内容。要测试你的服务器是否提供 gzip 文件,请访问gidnetwork.com/tools/gzip-test.php。此外,最好使用自动构建系统,该系统获取您的源文件,将其缩小,GZIP 压缩,并将其放置在您的托管服务器上的所需位置。蚂蚁[ant.apache.org/]、玛文[maven.apache.org/]等工具可以自动帮你做到这一点。

通过检查你最喜欢的网页检查器中的“时间线”标签来避免对 DOM 的回流和重绘。通过使用这个工具,您将能够看到当用户请求您的内容时,浏览器实际上在执行什么任务。通过在需要回流和/或重画之前处理所有的 DOM 设置,这将消耗更少的进程并提供更好的整体用户体验。图 10-4 展示了在 CNN.com 请求页面时,你的网页检查器中的时间线部分会是什么样子。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 10-4。浏览器的时间线检查器

正如你所看到的,当你输入网址后按回车键会发生很多事情。在本例中,您可以看到 HTTP 请求及其响应时间、脚本文件中的函数调用,甚至是对 DOM 的重画和渲染。此外,更重要的是,你甚至可以看到你正在检查的页面上有什么广告。真正有用的是,您可以检查 DOM 事件“content loaded”和“load”何时触发,并在需要深入研究特定于广告的优化之前获得对页面优化的更好评估。在这种情况下,触发 DOMContentLoaded 用了不到 1.6 秒,触发 Load 事件用了大约 2.8 秒。这对广告服务器来说很重要,因为服务器通常希望监听这些事件中的一个,并在主要内容呈现到屏幕上之后提供广告。这样你就可以确定页面是否需要更好的优化,你的广告内容或者两者都需要。

除了时间线中的“waterflow”视图,您还可以检查用于呈现页面内容的内存,包括 DOM 标记、样式、脚本甚至广告。图 10-5 显示了当你请求同一个页面时,内存部分的样子。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 10-5。浏览器的内存使用情况

在这张图片中,您会看到请求开始时出现了一个大尖峰,因为浏览器需要尽快填充所有 DOM 节点并解析脚本和样式。此外,在内容请求的开始,您可以看到仅向用户呈现页面就使用了将近 70MB 的内存。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 注意这些测量值取决于系统性能和网络连接速度。请自行进行代码优化。

在你的优化技术中使用的另一个重要工具是在你的浏览器的网页检查器中使用审计标签。审计功能允许开发人员对您请求的页面进行一些检查和平衡。在评估了页面内容、广告等之后,web inspector 将提供如何提高性能和加速页面渲染的提示。它可能会建议您压缩基于文本的文件,甚至删除没有呈现的元素上的样式声明。【http://johnpercival.org】图 10-6 展示了对我的域名的审计。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 10-6。浏览器的审计工具

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 注意我完全意识到我的领域需要优化,这就是为什么它是一个完美的测试案例。

对网络内容的优化分析适用于手机,也适用于桌面和其他使用网络连接的格式。习惯于检查和撕毁网页和广告,试图从你的内容中获得最小的数字足迹。再次提醒你,没有人会去网上看广告,除非你是制作广告的人。看电视广告也是如此。广告应该是有影响力的、引人注目的和吸引人的,而不是仅仅因为一些写得不好的广告代码正在吞噬系统资源就让你的计算机或设备负担过重。时刻牢记这一点,让网络成为每个人更好的体验。调试和优化是耗时的过程,只有经常重复地做,你才能掌握它们。这一章不会让你成为专家,但它会给你优势,并允许你使用各种伟大的工具来帮助你前进。这些工具中的一些可能会成为你的最爱,而另一些你甚至不会给第二次机会。我鼓励您在尝试其他方法的同时,找到适合您的开发工作流程。

移动提示和技巧

既然你已经对如何调试和优化你的内容有了一个好的想法,让我们来看看你在处理 HTML5 广告时通常会看到的一些常见的“陷阱”或陷阱,无论是在桌面上还是在移动设备上。让我们从 HTML 和 CSS 命名空间开始;如果您的广告中的任何标记与发布者页面上的元素同名,并且没有包装在 iframe 中,则该元素的样式和功能可能会继承到您的广告中。为了避免这种情况,通常的标准做法是在所有 ad 元素中使用前缀命名约定。我喜欢做广告服务前缀;例如,如果 AdMob 提供内容,它将是 am-container;PointRoll 应该是 pr-container。另一个很好的技巧是从 CSS 顶层元素向下命名空间。这可能是您的广告容器元素,因此您的所有 CSS 样式将被专门设置为广告元素,而不是出版商的页面。通过编写类似于 #adContainer 的东西。banner {…} 您可以通过 ID 明确定位广告容器,并定位嵌套元素,如我们示例中的 banner 类。

接下来我将讨论素材缓存。缓存经常是移动应用的一个问题,尤其是当用户注意到你的广告内容过时,但你知道你已经更新了它。确保您的客户端已退出应用/网络浏览器,清除了浏览器缓存,并从任何后台进程中删除了应用。在 iOS 的情况下,这可以通过双击设备的 home 按钮,轻按,并按住应用,直到出现关闭按钮来完成。对于 Android,你需要进入正在运行的应用并明确地终止它们的进程。

手机网络工具包

Webkit 有一个非常复杂的渲染引擎,它是 iOS 和 Android 设备的默认设备浏览器引擎。它也有许多有用但常常隐藏的属性可以利用。如果你注意到 Webkit 正在以一种奇怪的方式处理你的内容,甚至可能是一种理想的方式,但不太确定为什么,我建议访问 Webkit.org,了解这个强大的浏览器的内部工作方式。简单来说,我在这里列出了一些你在广告界最常遇到的例子。当您在创造性的开发、调试和测试中注意到一些有用的属性时,我希望这些有用的属性会对您有所帮助。第一个是当 Webkit 在 DOM 元素上执行任何类型的 CSS 动画时的字体渲染故障。当字体在动画中看起来清晰时,经常会出现这种故障,但在动画完成时,字体会无缘无故地变得更粗,并经常导致不必要的闪烁效果。如果您或您的客户注意到了这一点,请尝试对包装文本的容器 div 应用以下 CSS 规则:

<style>
.smoothFont {
        -webkit-backface-visibility: hidden;
        -webkit-transform: translate3d(0, 0, 0);
}
</style>

该规则将在广告体验期间将 GPU 设置为“开启”,这不会导致任何字体故障。还要记住,随着越来越多的浏览器利用 GPU,这个问题可能会在未来的浏览器版本中自行解决。另一个有用的 Webkit 技巧是防止 Safari 在设备方向改变时调整文本大小。旋转设备时,浏览器会调整文本大小。如果出于某种原因,您想防止这种影响,请使用下面的 CSS 规则:

<style>
.maintainSize {
        -webkit-text-size-adjust: none;
}
</style>

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 注意 text-size-adjust 是一个只有 Webkit 才有的 CSS 属性,允许你控制文本调整。

如果你是一个出版商,你会经常想要为你的移动访问者创建一个 web 应用体验。如果您负责构建广告将在其上运行的内容,并希望您的武器库中有一个方便的脚本来隐藏移动网页的默认工具栏,请查看以下代码片段,它可以附加到 DOM load 事件:

<script>
window.addEventListener('load', function() {
        setTimeout(scrollTo (0, 1));
}, false);
</script>

此外,既然我们在谈论手机,那么可以相当肯定地说,你生活在一个触摸世界。虽然这对于 UI 来说非常棒,但对于创建用户习惯于鼠标输入的传统行为来说,这确实带来了一些挑战。其中一个挑战是创建一个“悬停”效果,虽然这在技术上是不可能的,但你仍然可以让 UI 中的按钮做出反应,就好像它们真的被点击了一样。以下 JavaScript 示例可以帮助您模拟这种效果,这对于某些设计交互非常有用:

<script>
var myLinks = document.getElementsByTagName('a');

for(var i = 0; i < myLinks.length; i++){
        myLinks[i].addEventListener('touchstart', function () {
                this.className = "hover";
        }, false);
        myLinks[i].addEventListener('touchend', function (){
                this.className = "";
        }, false);
}
</script>

如您所见,您获取了所有的 a 标签,并在 touchstart 和 touchend 事件上添加了一个悬停类。现在,一旦您将 JavaScript 添加到文档中,您就可以像在 CSS 中一样使用 hover 类来设计样式了。

最后一个移动代码片段再次与触摸事件相关。您通常会注意到,当您与 DOM 中支持触摸的对象进行交互时,整个浏览器窗口都会移动,而不是您的目标对象。开发人员没有包括 preventDefault 方法,该方法在您用手指移动元素时告诉浏览器“后退”,通常会导致这种情况。加这个真的很简单,看看下面:

<script>
document.ontouchmove = function(event){
        event.preventDefault();
}
</script>

请记住,大多数情况下,出版商会包含特定的 HTML 元标签来锁定浏览器的视窗,但如果您需要在广告结束时解决这个问题,知道另一个选项仍然很好。

摘要

这一章充满了关于离线存储资源的有用的技巧和诀窍,离线使用的跟踪,以及一般的调试和优化。您深入了解了如何使用 HTML5 的 AppCache 缓存素材,以及哪些素材由于文件大小而不应该缓存。我讨论了在应用内部,这最终取决于出版商的要求,因为如果一个应用不支持离线,你的广告也不会得到支持。除了 HTML5 的应用缓存,您还将了解如何使用 navigator.onLine 检测您的 web 内容何时在线和离线,以及如何在应用中利用 SDK。我简要地谈到了新兴的 API,如网络连接 API,以及一旦规范最终确定,浏览器的采用,您将拥有一个非常好的 API 来为最终用户提供自适应的体验。在离线状态下,我讨论了如何在离线状态下使用离线跟踪技术来记录指标。无论您是使用缓存文件和 SDK 在应用中跟踪指标,还是在使用 DOM 存储或客户端数据库的移动设备上跟踪指标,请放心,您有能力完成这项工作。最后,我讨论了调试和优化这个复杂的主题。这个话题是我非常热衷的,如果你打算用 HTML5 在网上提供广告内容,你也应该如此。我涵盖了所有的工具和技术,您可以在您的指尖获得最小的文件大小,并分析您的广告内容跨多个屏幕。

当您思考离线、跟踪和调试时,您将进入 HTML5 动态广告的巨大领域。当你在广告中加入动态元素时,事情变得非常令人兴奋,但是它们的创建和调试也变得非常复杂。但是,请放心,您现在已经掌握了处理下一章主题的知识。

十一、使用 HTML5 的动态广告

动态广告在当今世界并不新鲜。用户和营销人员已经习惯于看到丰富创意与相关信息和数据相结合的概念。然而,这种动态行为传统上是使用 Flash 完成的,广告将引用外部 web 服务来更新其创意内容,这些内容可以是更新的文本、新图像,甚至是全新的广告体验。在这一章中,我将把重点放在帮助塑造动态广告市场的相同概念上,但我将主要关注 HTML5 和相关的开放网络技术。

让我们更深入地探讨“动态”这一主题,并弄清楚如何利用外部数据、发布者传递的数据、公共和私有 web 服务以及各种 API 来操纵广告投放时的创意。我将介绍基于地理定位的本地目标用户,并演示广告不一定要“嵌入”其中。我将回顾广告服务器和广告服务技术如何使用定制宏来帮助加速运行时动态,我还将展示广告如何能够及时、相关和高效地动态创建“热插拔”内容。使用这些技术,我将介绍您的广告将利用动态数据的技术,包括 XML、JSON 和直接 JavaScript。学习这些工具将最终打开在线广告的新世界。

交付规则

让我们从最基本的动态广告形式开始,它们是广告服务器的动态属性。通常,广告服务器可以为请求广告内容的用户设置传送规则。这种关系是这样的:“嘿,广告服务器,我是一个横向的 iPad 用户。给我一个不是基于 Flash 并且大小合适的创意。”然后,广告服务器将通过浏览器字符串(用户代理)查找来仔细检查用户是否确实在 iPad 上,然后将根据请求交付适当的创意类型。图 11-1 解释了用户和广告服务器之间的请求-响应关系。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 11-1。具有动态输入/输出值的典型广告服务器请求-响应

交付规则有很大的威力,因为它们是广告服务器的第一道入口;广告服务公司试图使这种广告响应超快,以便为观看内容的每个人留下印象。他们通常以毫秒为单位来判断这个响应时间。广告服务器不仅仅使用浏览器嗅探技术;它们可以嗅出用户 cookies 或存储在客户端浏览器缓存中的数据,以及 IP 地址、ISP 和其他各种数据,我将在后面介绍。递送规则或设置通常适用于如何通过请求用户的广告标签将广告提供给发布者页面。交付规则通常可以有频率、轮换和用户自定义规则以及与之相关联的特定创作类型。这些规则还可以与其他变量配对,例如一天中的时间、位置以及广告服务器可以分析的任何其他变量。我将在接下来的小节中逐一介绍这些技术。

频率是用户会看到广告的次数。如果活动持续一天,并且用户一天多次频繁访问发布者页面,则该用户可以在初始查看之后“限制频率”,并且此后提供不同的创意。 轮换简单来说就是一个用户在一次活动执行中可能看到多少不同的创意。如果广告商准备好了多个创意版本,广告服务器可以将它们轮流放置,这样用户就可以通过多个广告请求来观看新鲜内容。用户散列规则检测客户端浏览器或设备能够呈现什么。这可能是一个静态创意,Flash 创意,或 HTML5 创意。这实际上取决于客户端浏览器可以处理哪些功能,包括浏览器的特定功能。如果用户不能支持 HTML5,用户能支持 Flash 吗?如果没有,图像怎么样?

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 注意每个广告服务供应商都有不同的能力。接触他们,以确定什么对你和你的竞选活动有效。

利用这些广告服务设置,可以实现一些非常巧妙和动态的用例。例如,你可以通过相同的广告标签向 iPad 用户和智能电视用户提供创意。这使得发行商可以通过他们所有的分销渠道销售媒体,并让他们的 AdOps 团队高枕无忧,因为他们只需要传输一个标签。您能想象为每个移动设备、平板电脑、电脑、电视等处理多个标签有多难吗?很快就变得疯狂了!

随着广告服务器和技术供应商向其注入更多数据,交付规则变得更加强大。广告服务器可以分析的数据越多,广告体验就越定制。这种技术通常由所谓的动态创造性优化 (DCO) 驱动。DCO 引擎允许在许多变量甚至第三方变量或输入上提供动态创意。真正智能的 DCO 引擎可以考虑位置、性别、年龄、性取向和兴趣,以及许多其他输入值。利用这些有价值的数据,营销人员可以更有效地锁定他们的受众,知道他们想要触及哪些受众群体(以及哪些创意信息)。一些广告服务器甚至可以检测 WiFi 热点,并根据他们使用的网络服务相应地定向广告。例如,图 11-2 是我去年在三藩市参加会议时收到的。当我访问出版商网站Bloomberg.com时,广告服务器根据我的 IP 地址知道我在使用免费的会议 WiFi,并相应地定向广告。为了更好地理解这种动态能力,请看下面的一系列图片。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 11-2。Bloomberg.com上的初始屏幕使用 AT & T 的 3G 服务

这第一张图片是我在 iPad 上使用 AT & T 的 3G 网络时向Bloomberg.com发出的最初请求。如你所见,我在屏幕右侧看到一些广告。现在,如果我跳上会议的 w if I,正如你将在图 11-3 中看到的,我将看到更新的体验。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 11-3。屏幕使用旧金山的免费会议 WiFi

图 11-3 展示了我在 iPad 上进入设置应用打开会议的免费 WiFi 时的情况。图 11-4 展示了更新后的广告体验。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 11-4。使用免费 WiFi 服务后更新的【Bloomberg.com 站点

正如你从图 11-4 中看到的,我被广告服务器根据我的已知位置定向了一个特定的广告。因为我使用的是的免费 WiFi 服务,广告服务器知道我在哪里,可以根据那个 IP 地址提供相关的广告。现在如果我点击并按住广告,如图图 11-5 所示,你会看到广告服务器的域名。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 11-5。负责显示这些动态广告的广告服务器

如图 11-5 所示,你可以看到,当我点击并按住广告时,我看到的是这个广告单元的点击目的地,http://myturfads.com是广告服务器,负责识别我在免费网络上的 IP 地址,并呈现这些相关的动态广告。

发布者传递的数据

广告服务器本身就非常强大,当与 DCO 产品和动态交付规则结合使用时,它们真的非常强大。但有趣的是,广告服务器甚至可以使用出版商的数据来为广告体验带来更多动态。发布者传递的数据可以用于提供动态广告,方法是将发布者知道的访问者信息传递到广告服务器的广告标签中。该信息通常以字符串值的形式通过广告标签,通常以逗号或竖线分隔,但它通常可以在来自发布者的标签传递中加密,然后由广告服务器解密。这种加密是为了防止恶意行为在不知情的情况下利用用户的数据。发布者通常通过向用户/成员提供注册的免费服务来收集这些数据。这可能是一个电子邮件帐户,免费音乐流媒体帐户,甚至是一个社交网络。以下示例可以表示 ad 标记输入的许多值,如年龄、邮政编码、性别和兴趣:

var adInput = "29|19428|M|Business,Technology"

Or Base64 encoded:

var adInput = "Mjl8MTk0Mjh8TXxCdXNpbmVzcyxUZWNobm9sb2d5";

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 关于 Base64 编码的更多信息,请访问base64encode.org

如您所见,adInput 变量可能是广告服务器的广告标签的主要输入。然后,当广告在其页面上呈现时,发布者将填充数据。利用这种类型的数据传递的出版商有 Yahoo、MSN、AOL 和许多许多其他出版商,因为它允许在其用户群中使用更相关的广告方法。如果你还记得第一章,我提到过,大多数免费服务,如雅虎和谷歌,为他们的广告商提供庞大的用户群,以换取媒体费用。换句话说,出版商提供收集用户信息的免费服务。因此,用户是出版商出售的产品,广告商是出版商的客户。然而,这并不都是消极的。人们发现,使用这些丰富的集成将使您的活动提高十倍,因为它将正确的消息在正确的时间关联到正确的用户,用户可以从他们真正关心的广告中受益。

宏和变量

宏是我要介绍的最后一个广告服务功能。软件中的宏通常被用作临时替代值,以后会被替换。当您在 JavaScript 中引用其他值的地方使用变量时,您可能对此很熟悉。

一个简单的例子是 var man = john,其中 man 是变量,john 是值。更进一步,宏可以用于大量的服务器端值替换。例如,假设你开发了一个创意,你所有的点击链接都依赖于广告发布页面。如果是这种情况,而你没有宏指令,创意就需要用许多不同的方式来开发,以满足每一个位置。但是,对于宏,您可以使用这些替代宏值,并且在发布广告时,根据发布者的位置,这些值会被切换到正确的值。如果你向 CNN.com 和 BBC.com 提供相同的广告,下面的代码示例将更好地展示这个概念:

Ad server assignment forCNN.com:
MACRO= "http://www.cnn.com"

Ad server assignment for BBC.com:
MACRO= "http://www.bbc.co.uk"

HTML for creative:
<a href=MACRO target="_blank"></a>

正如您所看到的,以这种方式开发比在未来需要做出改变时更新大量创意更具可伸缩性。

使用 XML 和 JSON

到目前为止,从广告服务器的角度来看,您已经对广告如何动态地针对您这个用户有了相当的了解,但是让我们稍微转换一下话题,更多地讨论动态广告的技术方面,因为它们与 HTML5 和开放 Web 相关。尤其是在创意方面,你可以利用数据来操纵广告中的创意元素。但在你走上这条路之前,你需要弄清楚你的创意如何处理来自各种服务的外部数据。在 HTML5 中工作的两个最常见的通信层是可扩展标记语言(XML)和 JavaScript 对象符号(JSON) 。XML 和 JSON 在业界被广泛采用,因为它们被用于各种数据端点的许多 RESTful APIs 中。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 注意要获得 RESTful APIs 的详细信息,请访问blog.apigee.com/detail/restful_api_design

使用一种所有低级代码语言都能理解和解析的通用语言,可以让 web 开发人员轻松采用、交流和普及。从引入一个品牌的 Twitter feed 到引入一个股票行情自动收录器,甚至使用一个天气 feed 或当地零售产品,都可以被引入广告创意。传统上,这都是使用 XML 或 JSON 数据完成的,下面几节将展示使用 XML 和 JSON 与外部数据提供者合作的最佳方式。

XML

XML 可能是 web 服务最常用的语言。我不打算深入 XML 的本质,但是在广告世界中,广告会通过 HTTP 请求向某个 web 服务发出请求,通常带有一些必要的 URL 查询参数。web 服务对该请求提供的响应传统上是 XML 格式的。清单 11-1 展示了来自雅虎开放天气服务的请求和 XML 响应。

清单 11-1 。雅虎的天气 API XML 示例

HTTP Request:
http://query.yahooapis.com/v1/public/yql/jonathan/weather?zip=19428

Server Response:
<query yahoo:count="1" yahoo:created="2012-08-01T23:15:47Z" yahoo:lang="en US" xmlns:yahoo="http://www.yahooapis.com/v1/base.rng">
<results>
<channel>
<title>Yahoo! Weather - Conshohocken, PA</title>
<link>http://us.rd.yahoo.com/dailynews/rss/weather/Conshohocken__PA/*http://weather.yahoo.com/forecast/USPA0326_f.html</link>
<description>Yahoo! Weather for Conshohocken, PA</description>
<language>en-us</language>
<lastBuildDate>Wed, 01 Aug 2012 6:34 pm EDT</lastBuildDate>
<ttl>60</ttl>
<yweather:location city="Conshohocken" country="US" region="PA" xmlns:yweather="http://xml.weather.yahoo.com/ns/rss/1.0"/>
<yweather:units distance="mi" pressure="in" speed="mph" temperature="F" xmlns:yweather="http://xml.weather.yahoo.com/ns/rss/1.0"/>
<yweather:wind chill="70" direction="0" speed="0" xmlns:yweather="http://xml.weather.yahoo.com/ns/rss/1.0"/>
<yweather:atmosphere humidity="94" pressure="29.85" rising="2" visibility="4" xmlns:yweather="http://xml.weather.yahoo.com/ns/rss/1.0"/>
<yweather:astronomy sunrise="5:57 am" sunset="8:12 pm" xmlns:yweather="http://xml.weather.yahoo.com/ns/rss/1.0"/>
<image>
<title>Yahoo! Weather</title>
<width>142</width>
<height>18</height>
<link>http://weather.yahoo.com</link>
<url>http://l.yimg.com/a/i/brand/purplelogo//uh/us/news-wea.gif</url>
</image>
<item>
<title>Conditions for Conshohocken, PA at 6:34 pm EDT</title>
<geo:lat xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#">40.08</geo:lat>
<geo:long xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#">−75.3</geo:long>
<link>http://us.rd.yahoo.com/dailynews/rss/weather/Conshohocken__PA/*http://weather.yahoo.com/forecast/USPA0326_f.html</link>
<pubDate>Wed, 01 Aug 2012 6:34 pm EDT</pubDate>
<yweather:condition code="30" date="Wed, 01 Aug 2012 6:34 pm EDT" temp="70" text="Partly Cloudy" xmlns:yweather="http://xml.weather.yahoo.com/ns/rss/1.0"/>
<description>
<![CDATA[ <img src="http://l.yimg.com/a/i/us/we/52/30.gif"/><br /> <b>Current Conditions:</b><br /> Partly Cloudy, 70 F<BR /> <BR /><b>Forecast:</b><BR /> Wed - Scattered Thunderstorms. High: 82 Low: 66<br /> Thu - Partly Cloudy. High: 91 Low: 70<br /> <br /> <a href="http://us.rd.yahoo.com/dailynews/rss/weather/Conshohocken__PA/*http://weather.yahoo.com/forecast/USPA0326_f.html">Full Forecast at Yahoo! Weather</a><BR/><BR/> (provided by <a href="http://www.weather.com" >The Weather Channel</a>)<br/> ]]>
</description>
<yweather:forecast code="47" date="1 Aug 2012" day="Wed" high="82" low="66" text="Scattered Thunderstorms" xmlns:yweather="http://xml.weather.yahoo.com/ns/rss/1.0"/>
<yweather:forecast code="30" date="2 Aug 2012" day="Thu" high="91" low="70" text="Partly Cloudy" xmlns:yweather="http://xml.weather.yahoo.com/ns/rss/1.0"/>
<guid isPermaLink="false">
USPA0326_2012_08_02_7_00_EDT
</guid>
</item>
</channel>
</results>
</query>

从清单 11-1 中可以看到,该广告使用查询参数 zip=19428 向 http://query.yahooapis.com域发出 HTTP 请求,并获得一个有效的 XML 作为响应,其中包含用户定义的邮政编码的详细天气情况。这个真的很厉害!如果您从您的广告服务器中了解到,您可以让广告服务器在最初的广告请求中检测您的位置,将位置数据转换为邮政编码,并将该邮政编码传递给气象服务,以提供相关和最新的广告体验,这是用户在广告投放时真正关心的。

数据

JSON 与 XML 非常相似,它以层次结构来组织数据,但它的主要区别在于它实际上是由浏览器本地解析的 JavaScript 对象,而不管 XML 清单如何。JSON 和 JSON-P 的另一个好处是,它不关心它来自哪个领域。这意味着,如果托管信息的域(在本例中是 Yahoo)与发出请求的域(在本例中是 ad)不是同一个域,那么 XML 的响应就会受到影响。有办法绕过这种跨源策略,要么使用 CORS,你在第六章中了解到,要么简单地使用 JSON-P。有时 JSON-P 不是 web 服务响应数据格式的一个选项,但如果是,你就永远不需要担心处理 HTML5 广告时的域安全问题。以雅虎的天气服务为例,发出 JSON 请求与 XML 非常相似。清单 11-2 展示了使用 JSON 的同一个例子。

清单 11-2 。雅虎天气 API JSON 示例

Request:
http://query.yahooapis.com/v1/public/yql/jonathan/weather?zip=19428&format=json

Response:
{
    "query": {
        "count": 1,
        "created": "2012-08-01T23:29:00Z",
        "lang": "en-US",
        "results": {
            "channel": {
                "title": "Yahoo! Weather - Conshohocken, PA",
                "link": "http://us.rd.yahoo.com/dailynews/rss/weather/Conshohocken__PA/*http://weather.yahoo.com/forecast/USPA0326_f.html",
                "description": "Yahoo! Weather for Conshohocken, PA",
                "language": "en-us",
                "lastBuildDate": "Wed, 01 Aug 2012 6:53 pm EDT",
                "ttl": "60",
                "location": {
                    "city": "Conshohocken",
                    "country": "US",
                    "region": "PA"
                },
                "units": {
                    "distance": "mi",
                    "pressure": "in",
                    "speed": "mph",
                    "temperature": "F"
                },
                "wind": {
                    "chill": "72",
                    "direction": "0",
                    "speed": "0"
                },
                "atmosphere": {
                    "humidity": "94",
                    "pressure": "29.85",
                    "rising": "0",
                    "visibility": "5"
                },
                "astronomy": {
                    "sunrise": "5:57 am",
                    "sunset": "8:12 pm"
                },
                "image": {
                    "title": "Yahoo! Weather",
                    "width": "142",
                    "height": "18",
                    "link": "http://weather.yahoo.com",
                    "url": "http://l.yimg.com/a/i/brand/purplelogo//uh/us/news-wea.gif"
                },
                "item": {
                    "title": "Conditions for Conshohocken, PA at 6:53 pm EDT",
                    "lat": "40.08",
                    "long": "-75.3",
                    "link": "http://us.rd.yahoo.com/dailynews/rss/weather/Conshohocken__PA/*http://weather.yahoo.com/forecast/USPA0326_f.html",
                    "pubDate": "Wed, 01 Aug 2012 6:53 pm EDT",
                    "condition": {
                        "code": "30",
                        "date": "Wed, 01 Aug 2012 6:53 pm EDT",
                        "temp": "72",
                        "text": "Partly Cloudy"
                    },
                    "description": "\n<img src=\"http://l.yimg.com/a/i/us/we/52/30.gif\"/><br />\n<b>Current Conditions:</b><br />\nPartly Cloudy, 72 F<BR />\n<BR /><b>Forecast:</b><BR />\nWed - Scattered Thunderstorms. High: 82 Low: 66<br />\nThu - Partly Cloudy. High: 91 Low: 70<br />\n<br />\n<a href=\"http://us.rd.yahoo.com/dailynews/rss/weather/Conshohocken__PA/*http://weather.yahoo.com/forecast/USPA0326_f.html\">Full Forecast at Yahoo! Weather</a><BR/><BR/>\n(provided by <a href=\"http://www.weather.com\" >The Weather Channel</a>)<br/>\n",
                    "forecast": [{
                        "code": "47",
                        "date": "1 Aug 2012",
                        "day": "Wed",
                        "high": "82",
                        "low": "66",
                        "text": "Scattered Thunderstorms"
                    }, {
                        "code": "30",
                        "date": "2 Aug 2012",
                        "day": "Thu",
                        "high": "91",
                        "low": "70",
                        "text": "Partly Cloudy"
                    }],
                    "guid": {
                        "isPermaLink": "false",
                        "content": "USPA0326_2012_08_02_7_00_EDT"
                    }
                }
            }
        }
    }
}

正如您在清单 11-2 中看到的,请求几乎是相同的。唯一需要改变的是数据的格式。在这种情况下,您向名为 format=json *的请求添加一个额外的查询参数。*这又是一个非常强大的功能,它允许广告从不同的领域获取数据,而不需要“白名单”想一想当你可以动态地改变你的广告而不“实际上”改变它的可能性。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 注意有客户端 XML 到 JSON 的格式化程序(参见thomasfrank.se/xml_to_json.html),但是它们不能解决跨域策略的问题。

内容格式化

所以,你可能会问自己,这种动态数据很好,但我不需要处理和调节注入广告的数据吗?这是一个很棒的问题,显而易见的答案是肯定的!像使用脏话过滤器、添加省略号、调整文本大小、插入换行符代码等都需要考虑在内。

首先,脏话过滤器通常可以在后端或服务器端完成。在这些数据被输入到服务中之前,通常最好的做法是对针对该品牌的脏话和负面评论进行处理。也就是说,接触后端开发人员以确保这项技术到位总是好的。如果不是,清单 11-3 显示了一个很好的使用 JavaScript 的客户端脏话过滤器。

清单 11-3 。JavaScript 发誓过滤器示例

<html>
<head>
<script type="text/javascript">
//Grow this list for as long as you wish...
var keyWords = [D'oh,'jeez','dagnabit','boo','agh','Golly'];

function replaceChars(chr,cnt) {
  var s = '';
  for (var i=0; i<cnt; i++) {
    s += chr;
    console.log(s);
  }
  return s;
}

function checkWords() {
  var inputText = document.getElementById('textArea').value;
  var outputText = document.getElementById('conditionedText');

  for (var i=0; i < keyWords.length; i++) {
    var rg = new RegExp(keyWords[i]+' ',"ig");
    inputText = inputText.replace(rg,replaceChars('*',keyWords[i].length)+' ');
  }

  outputText.textContent = inputText;
}
</script>
</head>
<body>
<textarea id="textArea" rows="5" cols="13">
This chapter is dagnabit amazing!
</textarea>
<button onclick="checkWords()">Submit!</button>
<div id="conditionedText"></div>
</body>
</html>

你这么说真是太好了!如您所见,您可以向关键字数组中添加任意数量的单词,并且可以随意使用对您来说最有意义的单词。将 JSON 文件中的单词外部化也可能是一个更好的主意,这样就可以轻松地进行更新,而无需深入核心脚本文件。这也可以用于我们在第六章中学到的网络工作者。

另一种调节数据的方法是 CSS 的“HTML5 新特性”省略号文本属性。如果您不确定 web 服务返回的字数,您可以设置文本区域的宽度和高度值,并将文本区域内的副本设置为 overflow: ellipsis。看看清单 11-4 中的。

清单 11-4 。溢出省略号示例

<html>
<head>
</head>
<body>
<div id="textArea">
Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.
</div>
</body>
<style type="text/css">
#textArea {
  text-overflow: ellipsis;
  -o-text-overflow: ellipsis;
  -moz-text-overflow: ellipsis;
  -ms-text-overflow: ellipsis;
  -webkit-text-overflow: ellipsis;
  height: 100px;
  width: 200px;
  overflow: hidden;
  white-space: nowrap;
  padding: 5px;
}
</style>
</html>

现在,填充名为 textArea 的 div 的任何副本都将在副本的末尾附加一个省略号,以防单词溢出 div 容器。还有另一个对移动设备有用的 CSS 技巧,叫做 overflow: scroll。在移动设备(iOS 5 以上)上使用以下 CSS 将为您提供与本机操作系统类似的本机优雅滚动功能:

#textArea {
        overflow: scroll;
-webkit-overflow-scrolling: touch;
}

接下来,我将讨论随着数据和单词的增长而调整文本大小的概念。同样,在处理动态数据时,您不知道响应中有多少数据。除非您事先与可能采用字符限制的后端开发人员讨论这个问题,否则您将需要使用一些文本大小调整代码,您可以通过 JavaScript 利用这些代码来检测 div 容器的大小和填充容器的字数。使用 Nikolay Kuchumov 的位于jsfiddle.net/qW5h2/1的例子,你可以减小字体的大小,以适应其设计的分配空间。这有点棘手,如果副本明显减少,甚至会反过来咬你一口,特别是如果你的客户是制药公司,出于法律原因,每个字都需要清楚。最好的办法是与您的 web 服务提供商沟通,如果时间允许,他们可能会添加一个带有字体大小值的特殊节点。通过这种方式,ad 可以适当地检查该节点的值和大小,而无需执行任何逻辑。

我还想提到另一个技巧,那就是视口大小的概念。这对移动设备越来越重要。简而言之,视口大小/比例可以根据视口的缩放级别动态更新屏幕上字体的大小和比例。如果你在 vw *中使用 CSS 字体大小,这是需要注意的。*请记住,这将改变之前显示的容器大小方法,但是在这些技巧之间,您应该很好地了解什么技术最适合您和您的活动。更多关于视窗尺寸类型的信息,请访问css-tricks.com/viewport-sized-typography

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 注意还有一个非常好的轻量级 jQuery 插件叫做 FitText(fittextjs.com)用于响应字体大小。

HTML5 数据属性

现在,您已经了解了利用广告中的数据是多么有效,让我们来看看 HTML5 允许您在新的浏览器市场中使用的一些新功能。HTML5 中新增了可选的任意数据属性,可以在 HTML 标记中使用。以“宏和变量”一节中的例子为例,您可以在 HTML 中插入这些未定义的宏值,而不会影响您的有效标记。data 属性是向标记中添加动态值的好方法,而不用通过脚本将它们移植到 DOM 中。清单 11-5 展示了如何在你的广告中使用自定义数据属性,如果你想从一个零售商店的 web 服务中动态添加产品,比如来自(【http://shoplocal.com】??)的一个。

清单 11-5 。HTML5 数据属性示例

<!DOCTYPE HTML>
<html>
<head>
</head>
<body>
<div data-name="product" data-url="http://www.productURL.com"></div>
</body>
<script>
var element = document.getElementsByTagName('div')[0];
var name = element.dataset.name = "product"
var url = element.dataset.url = "http://www.productURL.com"
console.log('name' + name, 'url' + url)
</script>
</head>
</html>

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 关于ShopLocal.com零售 API 的更多信息,请访问aboutshoplocal.com/products/paperboy

data 属性只需使用 data-,其中代表您想要的任何值。在这种情况下,您使用名称和 URL,因为它们与产品信息相关,可以根据来自 Shoplocal API 的响应在您的广告中动态填充。只是重申一下,这可以是你想要的任何名字!发疯吧——这些都是有效的 HTML!

使用数据属性的真正好处是,通过添加的所有属性,您可以立即向用户显示信息,而不必担心发出任何额外的外部请求或进行任何服务器端查询。由于数据是放在标记中的,所以它已经存在了。这极大地提高了性能,因为数据已经存在于 DOM 中。您不需要“请求更多信息”,因为这些信息已经包含在初始回复中了。有关 HTML5 中自定义数据属性的更多详细信息,请访问html5doctor.com/html5-custom-data-attributes

H TML5 中另一个真正有用的新属性叫做 hidden。使用 hidden 属性时,浏览器不应呈现元素;但是,该元素在标记中仍然可见,并且可以从 DOM 中访问。当您想要显示元素时,可以使用 JavaScript 移除隐藏的属性。这很简单。清单 11-6 定义了一个隐藏的宏值。在 JavaScript 执行并检测到您的值被广告服务器替换后,您可以将元素及其值呈现到屏幕上供用户显示。这在您需要在将数据呈现给用户之前请求数据的情况下非常有用。

清单 11-6 。HTML5 隐藏属性示例

<!DOCTYPE HTML>
<html lang=en>
<head>
<script>
var output = document.getElementsByTagName('p')[0];

function onAdServerComplete (value) {
        // macro value
        var welcome = "Hello " + value;
        output.innerHTML = welcome;
        output.removeAttribute('hidden');
}

//Example Callback with value from AdServer
onAdServerComplete("John");
</script>
</head>
<body>
<p hidden>MACRO</p>
</body>
</html>

内容可编辑

下一个特性与其说是 API,不如说是属性,但它仍然是用户交互的重点,这是 HTML5 规范和动态数据的主要特性。信不信由你,内容可编辑自微软的 Internet Explorer 5.5 版本以来就已经存在,现在它在所有五种主要的现代浏览器中都得到支持。当使用内容可编辑特性时,您需要做的就是在您想要使之可编辑的元素上将 content editable 属性设置为 true。您还可以将此功能与推送至服务器或客户端存储的能力相结合,并管理更改,以便在用户再次体验时参考。清单 11-7 展示了 contenteditable 属性的作用。

清单 11-7 。内容可编辑示例

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset=utf-8>
<body>
<header contenteditable=true>Enter Some Text Here</header>
</body>
</html>

漂亮,简单,对吧?现在,您可以编辑 header 元素中的任何内容。实际上,您可以将该属性添加到 body 元素中,并允许编辑整个页面。广告中可编辑的内容有很大的潜力。实际上,您可以让用户编辑创意元素,允许他们创造性地改变自己的广告体验,而不是为所有用户输入使用输入字段。例如,如果您有一个广告活动,要求用户输入信息,允许他们定制、操作和编辑任何内容,包括广告本身的风格,会怎么样?这可能不是所有时候的理想情况,但对于特定的活动,这可能是一种独特的方法。当其他广告客户向他们的终端用户强行灌输信息时,这可以采取相反的方法,要求用户进行创造性的输入。这样,你就可以允许用户编辑整个广告,并将更改保存到浏览器或服务器上,下次他们按顺序查看广告时,就会看到他们曾经编辑过的最新保存版本。这也将允许品牌好好看看他们的用户是如何定制他们的品牌体验的,这将为品牌关系提供重要的细节。看一下清单 11-8 ,用户可以编辑广告体验的 CSS 样式,并将他们的更改保存到浏览器存储中。

清单 11-8 。内容可编辑广告示例

<!DOCTYPE html>
<head>
    <meta charset=utf-8>
<style type="text/css">
    * {
        -webkit-tap-highlight-color:rgba(0,0,0,0);
        outline: none;
        text-rendering: optimizeLegibility;
    }
    #cta {
        font: 175% sans-serif;
        text-align: center;
        margin-bottom: 20px;
    }
    #ad style{
        display: block;
        text-align: center;
    }
    #ad:hover{
        background-color: #999;
        width: 300px;
        height: 250px;
    }
    button {
      margin-top: 20px;
      margin-bottom: 20px;
      width: 300px;
      height: 30px;
    }
</style>
    <body align="center">
      <div id="cta">Edit Your Own CSS!</div>
        <div id="ad" contenteditable>
            <div id="style">
              <style contenteditable>
              #ad {
                  background-color: #fff;
                  width: 300px;
                  height: 250px;
                  border: 1px solid #000;
              }
              </style>
            </div>
        </div>
        <button id="clearValues">clear storage</button>
        <div id="output"></output>

        <script type="text/javascript">
        var adStyle = document.querySelector('#style'),
            clearIt = document.querySelector('#clearValues'),
            output = document.querySelector('#output');

        function adInit () {
            if (localStorage.getItem('adValue') === 'null' || localStorage.getItem('adValue') === null) {
                console.log('init')
            } else {
                adStyle.textContent = localStorage.getItem('adValue');
                console.log(localStorage.getItem('adValue'))
                output.textContent = "Values Loaded!!!";
            }

            adStyle.addEventListener('DOMCharacterDataModified', updateAdStyle, false);//Fires everytime a character is changed
            clearIt.addEventListener('click', clear, false);

            adStyle.focus();
        }

        function updateAdStyle () {
            if(localStorage) {
                output.textContent = "Values Saved!!!";
                console.log(adStyle.textContent);
                //store the values
                var styleFix = "<style contenteditable>" + adStyle.textContent + "</style>";
                localStorage.setItem('adValue', styleFix);
            }
        }

        function clear () {
            if(localStorage.getItem('adValue') != 'null' || localStorage.getItem('adValue') != null) {
              localStorage.clear();
            }
            output.textContent = "";
            console.log('clear')
        }
        window.addEventListener('DOMContentLoaded', adInit, false);

        </script>
</body>
</html>

正如您在前面的例子中看到的,您允许用户直接在页面上编辑 CSS,或者在本例中是 300 250 ad 单元。根据用户所做的编辑,在 localStorage 中存储一个名为 adValue 的长字符串值。现在,下一次用户查看广告时,这些值将被存储,并且仍然可以被操作。这真的打开了真正定制广告体验的大门。

HTML5 表格和输入

表单很可能是你第一次意识到你的网页内容可以变成交互式的。你不仅可以和你的用户互动,还可以根据他们的输入来定制你的网站和内容。这实质上是动态内容的整个基础。允许互动,优化反馈,并特别向与广告互动的用户呈现信息。也就是说,谈到动态广告,我不能不提到 HTML5 中表单和输入的更新。表单和输入标签长期以来一直与 Web 上的用户输入相关联。HTML5 表单最令人兴奋的新特性之一是使用客户端验证的能力。

以下是 HTML4 的前一种方法:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
</head>

<body>
<form>
        <input name="email" oninput=validate(this);>
</form>
</body>
</html>

function validate (input) {
...tons of validation code and regex magic
}

这是 HTML5 的新方法:

<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
</head>
<body>
<form>
    <input type=email required>
</form>
</body>
</html>

就这样!你注意到粗体字了吗?只要确保在 input 元素中包含所需的属性,浏览器就会处理输入验证。对于新手来说,这似乎合乎逻辑,没有什么了不起的,但实际上,在此之前,您需要包含一些长的 JavaScript 验证/regex 函数来检查字符串值,以确保它的格式良好,便于服务器处理。现在,浏览器会为您处理这一切。好好想想吧!每个开发人员都希望确保他们的输入得到正确的验证,所以如果每个开发人员都这样做,就让浏览器自己处理吧。为什么要为每个需要的项目重复自己?这也是 HTML5 努力实现的目标。

除了表单验证,HTML5 兼容的浏览器还包括本机数据类型,如日期、颜色、电子邮件、URL 和电话号码表单标记,所有这些都带有必要的客户端验证,正如您在前面的示例中所了解的。让我们分别来看看如何使用它们。首先,约会。

默认情况下,浏览器可以在浏览器的 UI 中为用户包含日历选择器元素。 图 11-6 展示了浏览器 Chrome 如何处理<输入 type = " date "></输入>。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 11-6。Chrome 浏览器如何处理日期输入

接下来是颜色输入。使用 可以告诉浏览器显示一个色轮供用户选择十六进制值,如图图 11-7 所示。请注意,并非所有的浏览器都处理这些输入。浏览器对于 UI 元素也有自己的视觉差异。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 11-7。Chrome 浏览器如何处理颜色输入

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 注意浏览器不能识别的任何输入类型都会优雅地降级为默认文本输入。

HTML5 还支持数字增量和滑块作为输入。只需添加以下输入,就可以让用户增加值并滑动一个简单的(但 CSS 可以换肤的) UI 元素。

<input type="number"></input>
<input type="range" min="1" max="5">range</input>

尝试之前的输入标签,你会注意到数字类型会在右边有箭头,范围类型会呈现一个简单的滑块,如图 11-8 中的所示。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 11-8。Chrome 浏览器如何处理数字和范围输入

这些新的(和旧的)输入格式真正有趣的是与它们相关联的新属性,比如占位符、必填项和真正酷的模式。这些属性中的每一个都有它自己的好处;例如,placeholder 属性允许输入字段显示一些示例文本,以表明用户应该输入什么样的文本格式。这对于特定的文本格式很有帮助,例如信用卡、电话号码,甚至是社会保险号。

正如您所了解的,required 是一个很好的属性,可以确保用户在提交之前填写表单中的某个部分。浏览器现在将检查是否需要任何输入,并在用户试图提交表单时标记它们。

模式属性本质上允许您直接在 HTML 标记中使用自己的正则表达式(regex)。传统上,这只能通过 JavaScript 来处理,如果您希望您的用户显式地输入诸如五位数的邮政编码之类的内容,您可以使用 regex 模式来确保在用户提交数据之前客户端验证已经就绪。清单 11-9 概述了我正在讨论的内容。

清单 11-9 。模式属性示例

<!DOCTYPE html>
<html>
<body>
<form>
  Zip code: <input type="tel" pattern="^\d{5}$" title="Five digit ZIP code" />
  <input type="submit" />
</form>
</body>
</html>

正则表达式是非常强大的代码,可以被调整以适应各种各样的用例。在前面的例子中,您使用的是^\d{5}$的 regex 模式,它确保用户输入正确的美国邮政编码的五位数。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 注意对于有用的正则表达式测试器/验证器,请访问regexpal.com

输入的另一个真正酷的地方是,您可以基于从用户交互(或非交互)中应用的伪类来定制您的 CSS。下面的 CSS 示例显示了如何为未验证的表单元素显示错误区域:

input {
     border: 1px solid #000000;
}
input:focus {
     border: 2px dashed #666666;
}
input:invalid {
     border: 5px solid #FF0000;
}

看看前面的 CSS 声明,您可以在焦点上更新边框粗细和颜色,当值无效时,为用户提供更大的边框粗细和亮红色表示“错误”

这些输入的另一个真正有用的特性是 datalist 元素。你是否曾经开始在 Google 上搜索某样东西,并注意到你正在搜索的主题已经被预先填充在输入框下面的列表中?嗯,使用 HTML5 datalist 元素,您可以在用户向 input 标签输入信息时提供类似的有用提示。如果用户试图通过一堆类别过滤广告,datalist 元素会非常有帮助。以之前的 ShopLocal retail 为例,可以向您的用户展示各种类别和产品的广告。为用户过滤它们不是很有帮助吗?让我们来看看下面的例子:

<body>
<input type="text" name="categories" list="categories" />

<datalist id="categories">
    <option value="Electronics">
    <option value="Furniture">
    <option value="Office Supplies">
    <option value="Kitchen">
    <option value="Bedding">
    <option value="Bath">
</datalist>
</body>

从代码中可以看出,您有一个名为 categories 的数据表,其中包含所有可能类别的选项值。现在,当用户开始在输入字段中输入内容时,使用名为 categories 的列表属性,您可以在用户输入时向他们显示选项。

表单并没有就此结束,它有很多改进,甚至工作组也在为 HTML5 和 HTML 制作更多的内容。也就是说,一个用于输入的成熟的 JavaScript 语音 API 正在开发中,目前谷歌 Chrome 浏览器的新版本支持该 API。显然是由 Google 的人带头的,您可以在浏览器中开始利用这一点,在您的输入标签中包含以下内容:

<input type="text" x-webkit-speech />

在输入标签中使用先前的 x-webkit-speech 属性将在输入文本区域产生图 11-9 。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 11-9。Chrome 浏览器如何支持语音输入

您还可以使用下面的代码片段解析输入语音的结果,方法是侦听传入的事件并从该事件中获取 results 对象。接下来,您将使用结果的发音和置信度注销到控制台,这是 speech API 中分析用户输入的两个属性。

<script>
input.addEventListener('webkitspeechchange', function(event) {
     if (event.results) {
          for (var i = 0, result; result = event.results[i]; ++i) {
          console.log('Speech: ' + result.utterance + ' ' + result.confidence);
     }
  }
}, false);
</script>

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 注意你可以去developer . Chrome . com/extensions/experimental . speech input . html了解更多关于 Chrome 的语音 API。

如果你熟悉语音到文本识别服务,比如 Dragon diction,甚至苹果的 Siri,这个功能对你和你的用户来说会非常熟悉和有用。有关 JavaScript speech API 工作规范的更多信息,请访问lists . w3 . org/Archives/Public/Public-web apps/2011 octdec/att-1696/speech API . html。所以,你可能会想,“如果一些浏览器不能识别它们,那么这些令人敬畏的属性有什么用呢?”好问题。一定要看看 http://caniuse.com 的或者利用 Modernizer 之类的工具(如果你有的话);否则,您可以像这样做一些简单的 JavaScript 检查:

<script>
if (!'x-webkit-speech' in document.createElement('input') ) {
    // no speech input
}  else {
    // speech!
}
</script>

最后,记住你的用户群,并记住不是所有的用户都有能力呈现现代网络的所有特性。

详细信息和汇总元素

细节元素是现代浏览器中一个伟大的新特性。你有没有想过最初只显示一点信息,然后在用户选择后显示更多信息,有点像手风琴打开/关闭的效果?嗯,细节元素可以帮助你快速做到这一点。看一下清单 11-10 ,它将细节元素合并到示例广告中。对于本例,假设您知道用户在哪里,并且希望根据他们的位置显示最近的商店。

清单 11-10 。详细信息/摘要示例

<!DOCTYPE HTML>
<html lang=en>
<head>
<style type="text/css">
        summary {
                -webkit-tap-highlight-color:rgba(0,0,0,0);
                        outline: none;/*removes outline*/
        }
        li:nth-child(odd) {
                background: #CCC;
                color: green;
        }
</style>
</head>
<body>
<details>
        <summary>Closest Store Locations</summary>
          <ul>
          <li><p>500 Ford Street, East Lanford IL 12345</p></li>
          <li><p>13 West Nectar Road, Brunswick FL 12345</p></li>
          <li><p>275 Bimba Drive, Clifton PA 12345</p></li>
          </ul>
</details>
</body>
</html>

如果您在浏览器中预览它,您会看到您可以打开和折叠信息,这是一个非常有用的 UI 元素,也可以通过 CSS 进行样式化。您甚至可以添加一些属性,比如 open,它允许浏览器在文档加载时默认打开 details 元素。您甚至可以将细节和摘要元素嵌套在一起,创建一个非常复杂的 UI 元素堆栈。从图 11-10 可以看出,在本文撰写之时,details 元素仅在 Chrome、Safari 6 和 Android 4.0 中受支持。但是,请注意这个元素,因为采用应该很快就会开始。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 11-10。对明细和汇总元素的支持。来源:http://caniuse.com/#feat=details

你可能会问自己,“等等!我们怎么知道用户在哪里?”这是一个很好的问题,我很高兴向您介绍下一部分。

地理定位

现代网络堆栈的另一个巨大的补充是地理定位 API。地理位置数据是用户的纬度和经度坐标。传统上,你需要利用像maxmind.com这样的网络服务,并经历一个查找用户 IP 地址并将其绑定到一个大概位置的过程。这不是防错的,因为它是由互联网服务提供商(ISP) 将 IP 分配给用户。(这可能是威瑞森、康卡斯特和其他你付费购买互联网服务的公司。)在我目前的使用案例中,使用 Comcast 的互联网服务,我的 IP 地址假设我在费城地区周围,这是在 WiFi 上,考虑到我只是在城外,这已经很好了;然而,我在某些情况下看到 IP 查找甚至不准确的状态。当用户使用手机运营商网络时,情况会越来越糟。因此,对于真正准确的使用,IP 位置查找是非常不可预测和不可靠的,尤其是对于移动设备。

幸运的是,有了新的地理定位 API,您可以获取用户的实际纬度和经度,这被证明是一个比昂贵(很少可靠)的查找服务更快、更准确的工具。我提到这个词昂贵的是因为这些查找工具中的一些不是免费的,因为它们向远程服务器和查找数据库发出请求来收集用户的大概位置,这反过来又会耗费时间。地理定位 API 通过浏览器在地理上定位用户(具有选择加入权限)。我强调“有权限”是因为一旦你试图检测到一个用户,浏览器的初始默认动作将提示用户一个警告,说明内容的域正在请求访问他们的位置。这个提示是所有浏览器和设备都采用的安全措施。图 11-11 展示了这是如何出现在谷歌的 Chrome 浏览器中的。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 11-11。谷歌 Chrome 浏览器中的地理定位提示

图 11-12 显示了它在 iDevice 的移动 Safari 浏览器上。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 11-12。手机 Safari 上的地理定位提示

如果用户选择、允许、拒绝或者只是等待太长时间才回复,那么开发人员可以根据执行的操作过程,通过检测 PERMISSION_DENIED、POSITION_UNAVAILABLE 或 TIMEOUT 来处理用户如何响应。在任何情况下,确保你的广告创意足够智能,以适应各种用户输入,因为不是每个人都允许基于位置的服务。清单 11-11 展示了如何使用 JavaScript 进行地理定位。

清单 11-11 。地理定位 API 示例

<!DOCTYPE html>
<head>
<meta charset=utf-8>
<body>
<header>
      <h1>geolocation</h1>
      <div id="coords"></div>
</header>
<script>
function success(position) {
  var lat = position.coords.latitude;
  var long = position.coords.longitude;
  document.getElementById('coords').innerHTML = "<p><strong>lat: </strong>" + lat + " <br><strong>long: </strong>" + long + "";
}

function error(error) {
    switch (error.code) {
    case error.PERMISSION_DENIED:
        alert("user did not share geolocation data");
        break;
    case error.POSITION_UNAVAILABLE:
        alert("could not detect current position");
        break;
    case error.TIMEOUT:
        alert("retrieving position timed out");
        break;
    default:
        alert("unknown error");
        break;
    }
}

function adInit(event) {
  console.log(event.type)
  if (navigator.geolocation) {
          navigator.geolocation.getCurrentPosition(success, error);
        } else {
          error('not supported');
        }
}

window.addEventListener('DOMContentLoaded', adInit, false);
</script>
</body>
</html>

正如您在前面的代码示例中看到的,您检查了 navigator.geolocation 对象,如果它是真的,您就知道您的浏览器或设备支持地理定位 API。之后,调用 navigator . geolocation . getcurrentposition 并传入两个参数,一个是成功回调函数,一个是错误回调函数。一旦您运行这个命令,用户将会注意到前一个提示的轮廓,并且用户将需要采取必要的操作。假设他们选择了 allow,它将通过 success 方法运行;否则,它将通过 error 方法运行,您可以通过查看在回调中收到的错误代码来处理错误发生的原因。

一旦用户允许共享他们的位置,您就可以从 position 对象中获取纬度和经度值,该对象随成功回调一起提供。有了这些位置信息,你可以将它与基于位置的服务联系起来,或者将纬度/经度地理编码到一个邮政编码中,以查询雅虎的天气服务或谷歌的地图服务等服务。底线是地理定位在广告环境中提供了一些丰富的体验。

广告中的地理定位

位置是网络广告的重要组成部分。如你所知,广告商希望通过尽可能多的必要方式锁定用户,以确保他们的媒体投资获得良好的投资回报。有了这个新的 API,开发人员可以做到这一点!当与谷歌、苹果或必应(Bing)等地图服务配对时,或者当您想要定位用户并通过向他们提供进入商店的详细指示来导航他们到最近的零售店时,这些位置信息非常有用。

及时和相关的广告大有帮助;例如,如果你来自芝加哥,注意到一个广告给你提供了关于英国伦敦的产品和方向的信息,这对广告商,更重要的是对你,最终用户来说,是非常浪费和无用的。广告商每年花费数百万美元通过各种输入来锁定受众。使用位置作为创意的输入,广告商能够向用户传递特定的动态信息,这实际上是为了与潜在消费者创建更加个性化的交互。品牌和广告商喜欢这种关系,因为它创造了回头客,因为用户最终会信任品牌。

好了,策略说够了。让我们来看一个地理定位的例子,在这个例子中,您根据用户的位置提供一个特定的位置,并利用 WatchPosition API 将用户导航到提供优惠的商店(参见清单 11-12 )。

清单 11-12 。地理位置广告示例

<!DOCTYPE html>
<html>
<head>
    <meta charset=utf-8>
</head>
    <body>
        <header>
            <h1>Find The Product!</h1>
            <div id="coords"></div>
        </header>
        <script>
            var MAGIC_LOCATION = "40.068134,-75.318797"//Don't be creepy
            var location = document.getElementById('coords');
            var watch;

            function success(position) {
                var lat = position.coords.latitude;
                var long = position.coords.longitude;
                location.innerHTML = "<p><strong>lat: </strong>" + lat + " <br><strong>long:
</strong>" + long + "";

                //start watching the users location
                watch = navigator.geolocation.watchPosition(updatePosition, error);
            }

            function error(error) {
                switch (error.code) {
                case error.PERMISSION_DENIED:
                    alert("user did not share geolocation data");
                    break;
                case error.POSITION_UNAVAILABLE:
                    alert("could not detect current position");
                    break;
                case error.TIMEOUT:
                    alert("retrieving position timed out");
                    break;
                default:
                    alert("unknown error");
                    break;
                }
            }

            function updatePosition(position) {
                var lat = position.coords.latitude;
                var long = position.coords.longitude;
                var newLocation = lat + ',' + long;
                //This fires everytime the users location changes
                if (newLocation === MAGIC_LOCATION) {
                    //You win!
                    productFound();
                    location.innerHTML = "<p><strong style='color:red'>" + newLocation + "</strong>";
                } else {
                    location.innerHTML = "<p><strong style='color:blue'>" + newLocation + "</strong>";
                }
            }

            function productFound() {
                navigator.geolocation.clearWatch(watch);
                window.alert("You Win!")
                //show coupon to the user to buy the product at the store
            }

            function adInit(event) {
                console.log(event.type)
                if (navigator.geolocation) {
                    navigator.geolocation.getCurrentPosition(success, error);
                } else {
                    console.error('geo not supported');
                    //supply different ad experience
                }
            }

            window.addEventListener('DOMContentLoaded', adInit, false);
        </script>
    </body>
</html>

正如你从这个例子中看到的,我已经扩展了它,使它成为一个独特的游戏。还记得“你是热的,暖的,还是冷的”游戏吗?你知道,就是用户试图在另一个人的帮助下盲目地寻找某样东西?现在,这可以在数字世界中复制!试着以这个例子为例,将其更新为使用您所在地区的商店位置。甚至可能设置一个时间限制。如果一个用户能在规定时间内找到它,他们会得到一个特别的优惠怎么样?这项技术的可能性是无限的。

同样,请记住地理定位是一个选择加入的过程,用户必须明确“同意”或“允许”该功能。确保处理用户可能做出的所有响应,并注意用户位置的轮询。有了这个 API,开发人员可以利用 watch position 方法,如果用户在移动中,它将持续检查用户的更新位置。虽然这对于提供准确和实时的方向非常有用,但请记住,您轮询和请求用户的确切位置越频繁,处理请求所消耗的电池和资源就越多。对于移动用户来说,最好将它保持在最低限度,甚至允许用户根据自己的意愿更新他们的位置。随着 Battery API 的最终确定和广泛采用,您可以使用更复杂的方法来检测当前电池百分比的状态,然后再进行位置轮询。地理定位为营销人员打开了新的广告世界,在日益增长的移动领域,用正确的信息抓住移动用户变得前所未有的重要。不相信我?看一下图 11-13 中来自 eMarketer.com 的图形。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 11-13。美国消费者对定位服务的使用

在图 11-13 中可以看到,location 挺大的,而且用得比较勤!如果你没有在下一个移动广告中使用它,我相信你会在客户要求后不久使用它。同样,地理位置 API 是一种规范,尽管它是独立的,但经常被合并到 HTML5 中。在 http://isgeolocationpartofhtml5.com 的亲自看看。然而,它确实与 HTML5 的许多新功能密切相关。如果你想了解更多关于地理定位规范的信息,请访问 http://dev.w3.org/geo/api/spec-source.html

位置的 Web 服务

在这一节的最后,我想看看其他一些针对位置和其他 API 的 web 服务。请记住,这些 API 有付费和免费两种版本,因此请根据您的活动目标和预算做出明智的选择。也许最受欢迎的位置 API 应该是谷歌的地图 API(developers.google.com/maps);然而,如果你计划在你的制作工作中使用谷歌地图,并且你期望从你的广告中获得大量的流量,你最终会为此付费,因为谷歌限制了其免费服务的请求数量。如果你负担不起谷歌,另一个很好的选择是开放的街道地图 API(openstreetmap.org),这是一个很好的免费服务,但往往缺乏谷歌的功能和地理信息。其他一些有用的定位服务有 IPinfoDB(ipinfodb.com/ip_location_api.php)、info chimps(infochimps.com)和 Open B Map(openbmap.org/api/openbmap_api.php5)。此外,如果美国法律不限制你,你可以利用在bluevia.com/en/page/tech.APIs.UserContextAPI找到的其他有用数据。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 注意小心处理这些信息。尽管广告商会恳求你跟踪和存储他们潜在客户的数据,但请注意,这可能并不总是符合人类的最佳利益,你可能会面临法律问题。

社会的

社交广告市场正在快速增长。如果你想一想,有什么比你的朋友在说什么更有活力和相关性呢?无论发生在哪个平台上,社交聊天总是在发生。使用社交平台,例如 four square(developer.foursquare.com/docs)、Facebook(developers.facebook.com)、Twitter(dev.twitter.com)、insta gram(instagram.com/developer)、LinkedIn(developer.linkedin.com/apis)、Google+(developers.google.com/+/API)、SoundCloud(developers.soundcloud.com)等等,开发人员和设计人员可以利用这些丰富的社交平台,为用户的社交图提供更加集成的体验。如果你的一个朋友喜欢耐克的活动,这些信息可以实时呈现给你。或者,如果你想看看对这部新电影预告片的评论,为什么不从这部电影的 Twitter 账户中引入标签呢?有了各种将社交数据引入广告的 API,这一切都成为可能。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 注意Open Graph API(ogp . me)允许用社交网络的元数据来标记网络内容和广告,以在用户的社交图中从网络内容创建丰富的对象。

社交 API

几乎每个人和他们的母亲都在脸书、推特或 Linkedin 上。我是说,连国王都在上面,而且他已经死了很多年了(twitter.com/ElvisPresley)]!社交几乎是当今互联网的主流;我们比历史上任何时候都更能接触和洞察人们在说什么,他们的感受如何,以及个人信息。更相关的是与我们的朋友、家人以及我们关注的其他人的对话。社交几乎是许多人的生活来源。请看一下图 11-14 中来自eMarketer.com的图形。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 11-14。对细节和摘要元素的支持

这就是证据!到 2014 年,超过一半的美国人将会与某种社交网络联系在一起。有了这些数据和将它们添加到广告中的潜在能力,包括地理定位。。。我想你明白我的意思;挺厉害的!在广告中加入社交元素可以很好地利用动态内容。说真的,还有什么比活生生的社交图更“活”的呢?有许多社交平台可以利用,但在利用这些社交 API 时,一定要记住权利和使用规则。像现在拥有 Instagram 的脸书这样的公司,允许开发者将他们的服务和平台整合到其他网络应用中;然而,在撰写本文时,脸书(和其他人)不允许你将用户的信息引入第三方广告体验。

同步单位

同步广告单元是指同一页面上的两个广告似乎在相互交流,从而为最终用户创造一种“捆绑在一起”的效果。这可以是从排行榜广告(728±90)单元开始并解析到盒子(300±250)单元的动画。同步单元通常由发行商一起出售,这通常是一个障碍,传统上,对于 Flash,您需要使用外部接口调用 JavaScript,以便在页面上的两个单元之间进行通信。既然你没有被“黑盒子”在 SWF 容器中,你的广告可以进行你自己特定的 JavaScript 调用来产生同步效果。看一下清单 11-13 ,其中 728 90 单位与 300 250 配套单位同步 CSS 过渡效果。

清单 11-13 。同步广告示例 728 广告

<!DOCTYPE HTML>
<html lang=en>
<head>
</head>
<style type="text/css">
#ad728 {
        position: absolute;
        top: 0px;
        left: 0px;
        width: 728px;
        height: 90px;
        border: 1px solid #000;
        font-family: Arial;
        font-size: 80px;
        background-color: red;
        color: black;
        opacity: 1;
        -webkit-transition-property: color;
        -webkit-transition-duration: 1s;
    -webkit-transition-timing-function: cubic-bezier(0.5, 0.2, 0.9, 0.4);
}
#ad728:hover {
        color: white;
}
</style>
<body align=center>
        <div id="ad728">728x90</div>
</body>
<script type="text/javascript">
        var ad300 = "stop";
        var ad728 = document.getElementById('ad728');
        var ad728value = window.getComputedStyle(ad728,null).getPropertyValue("color");

        ad728.addEventListener('webkitTransitionEnd', function(event) {
                if(ad728value === "red") {
                        ad300 = "play";
                } else {
                        ad300 = "stop";
                }
        }, false );
</script>
</html>

在本例中,您将看到 728 90 单位在其 CSS 颜色属性上获得了过渡效果。一旦用户悬停在 728 单元上,您将听到 webkitTransitionEnd 的事件,该事件在转换事件结束时触发。这很有用,因为现在您可以处理这些事件并启动其他函数。在这种情况下,您为 300 单元设置一个值来监听名为 ad300 的变量上的播放值。 清单 11-14 显示了 300 个单元监听从停止到播放的值变化。

清单 11-14 。同步广告示例 300 广告

<!DOCTYPE HTML>
<html lang=en>
<head>
</head>
<style type="text/css">
#ad300 {
        position: absolute;
        top: 0px;
        left: 0px;
        width: 300px;
        height: 250px;
        border: 1px solid #000;
        font-family: Arial;
        font-size: 50px;
        background-color: red;
        color: black;
        opacity: 1;
        -webkit-transition-property: color;
        -webkit-transition-duration: 1s;
    -webkit-transition-timing-function: cubic-bezier(0.5, 0.2, 0.9, 0.4);
}
</style>
<body align=center>
        <div id="ad300">300x250</div>
</body>
<script type="text/javascript">
        var checker300 = window.setInterval(check, 100);

        function check () {
                if (ad300 === "play") {
                        animate300();
                } else {
                        console.log('300 is stopped');
                }
        }

        function animate300 () {
                clearInterval(checker300);
                document.getElementById('ad300').style.color = 'white';
        }
</script>
</html>

如您所见,您触发了一个间隔来检查共享的 ad300 值,以确定是停止还是播放 300 单元的动画。对于这种类型的执行,有一些事情需要记住。首先,你需要知道出版商的页面是如何向你提供服务的。您是在 iframe、安全框架、MRAID 容器还是 CSS 溢出设置为隐藏的 div 中?这些都会影响到如何处理通过 JavaScript 的交流。例如,如果在一个包含 overflow : hidden 的 div 中为您提供发布者页面,您需要做的就是让两个广告在脚本中以相同的共享值进行通信(就像前面的示例)。同样,将 0 设置为 1 可以做到这一点,当该值发生变化时,让“checker”间隔轮询会很有帮助。此外,您可以从 728 单元为 300 单元分派定制事件来监听和处理。如果你通过某个容器(iframe 或 MRAID)接受服务,你需要通过该容器进行通信,以便广告连接。考虑到此时两个广告都将被包装,这有点棘手,如果它跨广告网络运行,就不知道容器会是什么,除非您有一个广告加载程序脚本文件,其唯一的工作是检测广告投放的环境。如果是 iframe,假设你有读写值的权限,你应该能够定位父窗口。如果是在 MRAID,你需要看看是否有某些 MRAID 或出版商的电话,以便让广告传输数据。

此外,您可能认为轮询值并不是一种真正优化的技术。事实并非如此,一些浏览器会在一定时间后简单地去除重复出现的间隔调用。幸运的是,HTML5 还有一个新特性,叫做跨文档消息传递的通信 API。它非常适合同步广告开发!

通信 API

用于跨文档消息传递的通信 API 允许通过窗口对象进行传输,而不管域安全性以及内容是否包装在发布者页面上的 iframe 中。基本上,如果你想发送信息给另一个广告,说“嘿,300 单位,这是 728 单位告诉你动画!”然后,您可以让发布者的页面或页面上的其他元素(从不同的域托管)侦听消息并做出相应的反应。这是通过使用一种叫做 postMessage 的方法来完成的;清单 11-15 展示了修改后的同步广告示例。

清单 11-15 。通信 API 728 示例

<!DOCTYPE HTML>
<html lang=en>
<head>
        <style type='text/css'>
#ad728 {
        position: absolute;
        top: 0px;
        left: 0px;
        width: 728px;
        height: 90px;
        border: 1px solid #000;
        font-family: Arial;
        font-size: 80px;
        background-color: red;
        color: rgb(0, 0, 0);
        opacity: 1;
        -webkit-transition-property: color;
        -webkit-transition-duration: 1s;
    -webkit-transition-timing-function: cubic-bezier(0.5, 0.2, 0.9, 0.4);
}
#ad728:hover {
        color: rgb(255, 255, 255);
}
</style>
</head>
<body align=center>
        <div id='ad728'>728x90</div>
</body>
<script type='text/javascript'>
var ad728 = document.getElementById('ad728'),
        ad728value;

function adInit () {
        console.log('adInit');
        ad728.addEventListener('webkitTransitionEnd', nudge300, false);
}

function nudge300 (event) {
        console.log(event);
        ad728value = window.getComputedStyle(ad728,null).getPropertyValue('color');

        if (ad728value === 'rgb(255, 255, 255)') {
                if(typeof window.postMessage === 'undefined'){
                        console.error('Your browser does not support the communication API');
                        //fail over to our other method
                } else {
                        //Same Domain
                        console.log('Message: ' + window.postMessage)
                        window.postMessage('play300', 'http://johnpercival.org');//Insert your domain here

                        //Cross Domain
                        //document.getElementsByTagName('iframe')[0].contentWindow.postMessage('play300', 'http://johnpercival.org');
                }
        } else {
                //some other color
                console.log(ad728value);
        }
};

window.addEventListener('load', adInit, false);
</script>
</html>

首先,像前面一样设置 728 单元,但主要区别是您使用了一个接受两个参数的 postMessage 调用。第一个是要传递的字符串值,第二个是窗口对象的域(在本例中是我的域,但一定要使用托管文件的域),通常是 ad 服务器。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 注意如果不太在意域名来源,可以传递一个文字字符串值*,它是通配符,允许所有域名转移。

现在,一旦用户悬停在 728 单元上,您就可以向任何收听者发布消息。在这种情况下,它将是 300 单位,如清单 11-16 中的所示。

清单 11-16 。通信 API 300 示例

<!DOCTYPE HTML>
<html lang=en>
<head>
        <style type="text/css">
#ad300 {
        position: absolute;
        top: 0px;
        left: 0px;
        width: 300px;
        height: 250px;
        border: 1px solid #000;
        font-family: Arial;
        font-size: 50px;
        background-color: red;
        color: black;
        opacity: 1;
        -webkit-transition-property: color;
        -webkit-transition-duration: 1s;
    -webkit-transition-timing-function: cubic-bezier(0.5, 0.2, 0.9, 0.4);
}
</style>
</head>
<body align=center>
        <div id="ad300">300x250</div>
</body>
<script type="text/javascript">

function adInit () {
   window.addEventListener('message', messageHandler, true);
   console.log('adInit')
}

function messageHandler(event) {
   switch(event.origin) {
      case "http://johnpercival.org":
        //only listen for events from our domain
         if(event.data === 'play300') {
                animate300();
         } else {
                //not our 300's message to animate
         }
         break;
   }
}

function animate300 () {
        document.getElementById('ad300').style.color = 'white';
}

window.addEventListener('load', adInit, false);
</script>
</html>

在接收器中,300 单位,非常简单。您设置了一个事件监听器来监听消息事件,并使用 messageHandler 函数对其进行相应的处理。在该处理程序中,您检查事件的来源,确保它来自johnpercival.org或您选择的域,最后检查附加到该事件的数据是否具有 play300 *的值。*如果是这样,你只需调用 animate300 方法来创建同步效果。

虽然这只是剥猫皮的一种方式,但是还有很多其他方式可以达到你想要的效果。请记住,这种风格可以在两个单元之间共享。请记住,我说过保持名称间距以广告服务器供应商为前缀,例如 AdServer-AdContainer。在向页面交付同步单元的情况下,我建议在名称空间前加上单元的大小。所以,AdServer-AdContainer 就变成了 AdServer-300x250-Container。这有点冗长,但适当地保留这个前缀将确保你的风格和其他事件不会在广告中共享,甚至在页面内容中共享。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 注意这种方法可以用于在出版商的页面内容和托管在其他域上的广告之间传输数据。

高级动力学

高级动力学是真正令人兴奋的地方。当集成多个 HTML5 特性、web 服务、API 和 publisher 买入时,您可以创建一个前沿的活动。没有什么可以阻止你使用位置数据、天气服务、商店查询服务、股票订阅,甚至要求用户提供一些输入来定制和制作个性化的广告体验。当然,这需要时间、精力和金钱来完成,但是执行起来会很惊人,并且对最终用户非常有用。

通常,你会陷入寻找一个 web 服务来满足你的需求。在这种情况下,请查看 GitHub 上的开发人员社区并四处询问。如果您有服务器端编码技能,那么您可以自己编写,甚至向客户展示创建 web 服务的额外成本。这可能会让客户不想要这项服务,或者他们可能会请求这项服务,并将其用于未来的许多其他活动。

动态视频

我在第七章里讲了很多关于视频的内容,但是没有过多提到动态视频。在我完全沉浸在 HTML5 开发中之前,我非常喜欢 ActionScript 和 After Effects 中的组合数据。我做了一些很酷的例子,你可以动态地更新和改变叠加在视频上的内容。这些内容将通过元数据与视频的移动、倾斜、旋转和缩放具体联系起来,并由 SWF 读入,以创建无缝的视频/动画效果。尽管技术发生了很大的变化,但理论是不变的。使用 HTML5 canvas 和 video、WebVTT、CSS3 transforms 和 JavaScript 的特性,您可以做非常类似的事情。甚至还有一些有用的库,用于将数据实时绑定到视频内容。看看 PopcornJS(popcornjs.org),你就会明白我在说什么了。

摘要

我在本章中讲述了很多,包括从您的广告服务器的各种输入中动态提供广告,使用交付规则,使用发布者传递的数据,使用 XML 和 JSON,使用 HTML5 中的新功能,如 data 属性,使用 contenteditable,使用表单,使用各种有用的属性,以及使用来自浏览器的惊人的新地理位置数据。我甚至讨论了一些关于社交 API 和广告集成、高级动态执行和流行的同步广告单元的内容。

请随意花些时间访问代码示例并自行测试。动态广告可以做很多事情,只要你有信息和数据可以利用,真的没有限制。请记住,不是每个广告都应该是动态的。如果你专门针对移动设备上的用户,记住他们的用户体验。在带宽不充足的情况下,用户可能处于明显减少的连接中。如果是这种情况,我建议在广告请求时检测到这一点,并提供替代版本的广告体验。*不要对用户的机器征税!*最后,你真的想提供一个有品位的、有效的广告体验,而不是一个霸占所有系统资源、呈现糟糕体验、用户会责怪品牌甚至出版商的广告体验。如今,用户比以往任何时候都聪明,他们拥有人类已知的所有社交渠道,让你意识到自己搞砸了。最后,为你的用户提供良好的体验,了解网络条件是一个变量,并随时调整。保持活力,适应变化。

我希望你喜欢这一章;这是下一个讨论的很好的入门,前沿的 HTML5。现在你已经知道了 HTML5 广告的基本知识,以及如何在你的广告中包含动态,我将谈论一些在不久的将来即将出现或者可能已经出现在新兴 web 标准中的真正令人惊奇的特性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值