Оптимизация поведения щелчков WKWebView

Выберите платформу: Android (бета-версия)Новый Android iOS

Если ваше приложение использует WKWebView для отображения веб-контента, вам, возможно, стоит оптимизировать поведение при кликах по следующим причинам:

  • WKWebView не поддерживает просмотр веб-страниц во вкладках. При нажатии на рекламу, пытающуюся открыть новую вкладку, по умолчанию ничего не происходит.

  • При клике на рекламу, открывающуюся в той же вкладке, страница перезагружается. Возможно, вам захочется принудительно открывать рекламу вне WKWebView , например, если вы размещаете игры на H5 и хотите сохранить состояние каждой игры.

  • Функция автозаполнения не поддерживает ввод данных кредитных карт в WKWebView . Это может привести к снижению конверсии в электронной коммерции для рекламодателей, что негативно скажется на монетизации веб-контента.

В этом руководстве представлены рекомендуемые шаги по оптимизации поведения при кликах в мобильных веб-версиях с сохранением содержимого веб-страницы.

Предварительные требования

Выполнение

В рекламных ссылках атрибут href target может быть установлен на _blank , _top , _self или _parent . Рекламные ссылки также могут содержать функции JavaScript, такие как window.open(url, "_blank") .

В следующей таблице описано, как каждая из этих ссылок ведет себя в веб-представлении.

атрибут href target Стандартное поведение клика WKWebView
target="_blank" Ссылка не обрабатывается веб-представлением.
target="_top" Обновите ссылку в существующем веб-представлении.
target="_self" Обновите ссылку в существующем веб-представлении.
target="_parent" Обновите ссылку в существующем веб-представлении.
Функция JavaScript Стандартное поведение клика WKWebView
window.open(url, "_blank") Ссылка не обрабатывается веб-представлением.

Выполните следующие действия, чтобы оптимизировать поведение при кликах в вашем экземпляре WKWebView :

  1. Настройте WKUIDelegate для вашего экземпляра WKWebView .

  2. Установите WKNavigationDelegate для вашего экземпляра WKWebView .

  3. Определите, следует ли оптимизировать поведение URL-адреса клика.

    • Проверьте, соответствует ли свойство navigationType объекта WKNavigationAction типу клика, который вы хотите оптимизировать. В примере кода проверяется наличие свойства .linkActivated , которое применяется только к кликам по ссылке с атрибутом href .

    • Проверьте свойство targetFrame объекта WKNavigationAction . Если оно возвращает nil , это означает, что целью навигации является новое окно. Поскольку WKWebView не может обрабатывать такие клики, их необходимо обрабатывать вручную.

  4. Решите, следует ли открывать URL-адрес во внешнем браузере, в SFSafariViewController или в существующем веб-представлении. Приведенный фрагмент кода показывает, как открывать URL-адреса, ведущие за пределы сайта, путем отображения SFSafariViewController .

Пример кода

Приведенный ниже фрагмент кода демонстрирует, как оптимизировать поведение клика по веб-представлению. В качестве примера он проверяет, отличается ли текущий домен от целевого домена. Это лишь один из подходов, поскольку используемые вами критерии могут различаться.

Быстрый

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

в ваше веб-представление. Щелкните по каждому из различных типов ссылок, чтобы увидеть, как они работают в вашем приложении.

Вот что следует проверить:

  • Каждая ссылка открывает нужный URL-адрес.
  • При повторном входе в приложение счетчик на тестовой странице не сбрасывается до нуля, чтобы подтвердить сохранение состояния страницы.