优化点击行为

如果您的应用使用 WKWebView 显示 Web 内容,您可能需要 考虑优化点击行为,原因如下:

  • WKWebView 不支持 标签式浏览。默认情况下,尝试打开新标签页的广告点击不会执行任何操作。

  • 在同一标签页中打开的广告点击会重新加载页面。您可能需要强制 广告点击在 WKWebView 外部打开,例如,如果您托管 H5 游戏 并希望 保持每个游戏的状态。

  • 自动填充功能不支持在 WKWebView 中填写信用卡信息。这可能会导致广告客户的电子商务转化次数减少,从而对 Web 内容的创收产生负面影响。

本指南提供了优化移动 Web 视图中的点击行为并保留 Web 视图内容的建议步骤。

前提条件

实现

广告链接的 href target 属性可以设置为 _blank_top_self_parent。广告链接还可以包含 JavaScript 函数,例如 window.open(url, "_blank")

下表介绍了这些链接在 Web 视图中的行为方式。

href 目标属性 默认 WKWebView 点击行为
target="_blank" Web 视图不处理 链接。
target="_top" 在现有 Web 视图中重新加载链接。
target="_self" 在现有 Web 视图中重新加载链接。
target="_parent" 在现有 Web 视图中重新加载链接。
JavaScript 函数 默认 WKWebView 点击行为
window.open(url, "_blank") Web 视图不处理 链接。

如需优化 WKWebView 实例中的点击行为,请按以下步骤操作:

  1. WKWebView 实例上设置 WKUIDelegate

  2. 在 实例上设置 WKNavigationDelegateWKWebView

  3. 确定是否优化点击跟踪网址的行为。

    • 检查 navigationType 对象上的 WKNavigationAction 属性是否是您要优化的点击类型。该 代码示例 检查 .linkActivated ,该属性仅适用于点击带有 href 属性的链接。

    • 检查 targetFrame 对象上的 WKNavigationAction 属性。如果该属性返回 nil,则表示导航的目标是新窗口。由于 WKWebView 无法处理该点击,因此必须手动处理这些点击。

  4. 确定是在外部浏览器、 SFSafariViewController还是现有 Web 视图中打开网址。代码段展示了如何通过呈现 SFSafariViewController 来打开离开网站的网址。

代码示例

以下代码段展示了如何优化 Web 视图点击行为。例如,它会检查当前网域是否与目标网域不同。这只是一种方法,您使用的条件可能会有所不同。

Swift

import GoogleMobileAds
import SafariServices
import WebKit

class ViewController: UIViewController, WKNavigationDelegate, WKUIDelegate {

  override func viewDidLoad() {
    super.viewDidLoad()

    // ... Register the WKWebView.

    // 1. Set the WKUIDelegate on your WKWebView instance.
    webView.uiDelegate = self;
    // 2. Set the WKNavigationDelegate on your WKWebView instance.
    webView.navigationDelegate = self
  }

  // Implement the WKUIDelegate method.
  func webView(
      _ webView: WKWebView,
      createWebViewWith configuration: WKWebViewConfiguration,
      for navigationAction: WKNavigationAction,
      windowFeatures: WKWindowFeatures) -> WKWebView? {
    // 3. Determine whether to optimize the behavior of the click URL.
    if didHandleClickBehavior(
        currentURL: webView.url,
        navigationAction: navigationAction) {
      print("URL opened in SFSafariViewController.")
    }

    return nil
  }

  // Implement the WKNavigationDelegate method.
  func webView(
      _ webView: WKWebView,
      decidePolicyFor navigationAction: WKNavigationAction,
      decisionHandler: @escaping (WKNavigationActionPolicy) -> Void)
  {
    // 3. Determine whether to optimize the behavior of the click URL.
    if didHandleClickBehavior(
        currentURL: webView.url,
        navigationAction: navigationAction) {
      return decisionHandler(.cancel)
    }

    decisionHandler(.allow)
  }

  // Implement a helper method to handle click behavior.
  func didHandleClickBehavior(
      currentURL: URL,
      navigationAction: WKNavigationAction) -> Bool {
    guard let targetURL = navigationAction.request.url else {
      return false
    }

    // Handle custom URL schemes such as itms-apps:// by attempting to
    // launch the corresponding application.
    if navigationAction.navigationType == .linkActivated {
      if let scheme = targetURL.scheme, !["http", "https"].contains(scheme) {
        UIApplication.shared.open(targetURL, options: [:], completionHandler: nil)
        return true
      }
    }

    guard let currentDomain = currentURL.host,
      let targetDomain = targetURL.host else {
      return false
    }

    // Check if the navigationType is a link with an href attribute or
    // if the target of the navigation is a new window.
    if (navigationAction.navigationType == .linkActivated ||
      navigationAction.targetFrame == nil) &&
      // If the current domain does not equal the target domain,
      // the assumption is the user is navigating away from the site.
      currentDomain != targetDomain {
      // 4. Open the URL in a SFSafariViewController.
      let safariViewController = SFSafariViewController(url: targetURL)
      present(safariViewController, animated: true)
      return true
    }

    return false
  }
}

Objective-C

@import GoogleMobileAds;
@import SafariServices;
@import WebKit;

@interface ViewController () <WKNavigationDelegate, WKUIDelegate>

@property(nonatomic, strong) WKWebView *webView;

@end

@implementation ViewController

- (void)viewDidLoad {
  [super viewDidLoad];

  // ... Register the WKWebView.

  // 1. Set the WKUIDelegate on your WKWebView instance.
  self.webView.uiDelegate = self;
  // 2. Set the WKNavigationDelegate on your WKWebView instance.
  self.webView.navigationDelegate = self;
}

// Implement the WKUIDelegate method.
- (WKWebView *)webView:(WKWebView *)webView
  createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration
             forNavigationAction:(WKNavigationAction *)navigationAction
                  windowFeatures:(WKWindowFeatures *)windowFeatures {
  // 3. Determine whether to optimize the behavior of the click URL.
  if ([self didHandleClickBehaviorForCurrentURL: webView.URL
      navigationAction: navigationAction]) {
    NSLog(@"URL opened in SFSafariViewController.");
  }

  return nil;
}

// Implement the WKNavigationDelegate method.
- (void)webView:(WKWebView *)webView
    decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction
                    decisionHandler:
                        (void (^)(WKNavigationActionPolicy))decisionHandler {
  // 3. Determine whether to optimize the behavior of the click URL.
  if ([self didHandleClickBehaviorForCurrentURL: webView.URL
      navigationAction: navigationAction]) {
    decisionHandler(WKNavigationActionPolicyCancel);
    return;
  }

  decisionHandler(WKNavigationActionPolicyAllow);
}

// Implement a helper method to handle click behavior.
- (BOOL)didHandleClickBehaviorForCurrentURL:(NSURL *)currentURL
                    navigationAction:(WKNavigationAction *)navigationAction {
  NSURL *targetURL = navigationAction.request.URL;

  // Handle custom URL schemes such as itms-apps:// by attempting to
  // launch the corresponding application.
  if (navigationAction.navigationType == WKNavigationTypeLinkActivated) {
    NSString *scheme = targetURL.scheme;
    if (![scheme isEqualToString:@"http"] && ![scheme isEqualToString:@"https"]) {
      [UIApplication.sharedApplication openURL:targetURL options:@{} completionHandler:nil];
      return YES;
    }
  }

  NSString *currentDomain = currentURL.host;
  NSString *targetDomain = targetURL.host;

  if (!currentDomain || !targetDomain) {
    return NO;
  }

  // Check if the navigationType is a link with an href attribute or
  // if the target of the navigation is a new window.
  if ((navigationAction.navigationType == WKNavigationTypeLinkActivated
      || !navigationAction.targetFrame)
      // If the current domain does not equal the target domain,
      // the assumption is the user is navigating away from the site.
      && ![currentDomain isEqualToString: targetDomain]) {
     // 4. Open the URL in a SFSafariViewController.
    SFSafariViewController *safariViewController =
        [[SFSafariViewController alloc] initWithURL:targetURL];
    [self presentViewController:safariViewController animated:YES
        completion:nil];
    return YES;
  }

  return NO;
}

测试网页导航

如需测试网页导航更改,请将

https://google.github.io/webview-ads/test/#click-behavior-tests

加载到 Web 视图中。点击每种不同的链接类型,了解它们在应用中的行为方式。

以下是一些需要检查的事项:

  • 每个链接都会打开预期的网址。
  • 返回应用时,测试页面的计数器不会重置为零,以验证页面状态是否已保留。