Expand my Community achievements bar.

Issues with Adobe Analytics integration on iOS using WKWebView

Avatar

Level 1

Hello,

 

I am currently working on integrating Adobe Analytics into an iOS application using WKWebView. The integration works perfectly on Android, confirming that the credentials (s_account and trackingServer) are correct.

 

Problem: While this code successfully injects and executes the AppMeasurement script on Android devices, it does not seem to log any data in Adobe Analytics when tested on iOS devices. The appMeasurementInitialization script is executed without errors, as evidenced by the alerts and console logs, but no data appears in Adobe Analytics.

 

Question: Could you please provide guidance on what might be causing this issue specifically on iOS devices? Are there any additional configurations or considerations required for Adobe Analytics integration with WKWebView on iOS?

 

Here's a snippet of the Swift code I'm using:

 

 

import UIKit
import WebKit

class ViewController: UIViewController, WKNavigationDelegate, WKUIDelegate {

    var webView: WKWebView!

    override func viewDidLoad() {
        super.viewDidLoad()

        // Initialize WKWebView and load URL
        let config = WKWebViewConfiguration()
        let userContentController = WKUserContentController()

        if let appMeasurementScript = readAppMeasurementJS() {
            let userScript = WKUserScript(source: appMeasurementScript, injectionTime: .atDocumentEnd, forMainFrameOnly: false)
            userContentController.addUserScript(userScript)
        }

        config.userContentController = userContentController
        webView = WKWebView(frame: self.view.bounds, configuration: config)
        webView.navigationDelegate = self
        webView.uiDelegate = self
        self.view.addSubview(webView)

        if let url = URL(string: "http://example.com") {
            let request = URLRequest(url: url)
            webView.load(request)
        }
    }

    // Function to read AppMeasurement.js from bundle
    private func readAppMeasurementJS() -> String? {
        if let filepath = Bundle.main.path(forResource: "AppMeasurement", ofType: "js") {
            do {
                let contents = try String(contentsOfFile: filepath)
                return contents
            } catch {
                print("Failed to read AppMeasurement.js")
                return nil
            }
        }
        return nil
    }

    // Inject additional script after page load
    func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
        let appMeasurementInitialization = """
            var s_account='accountID';
            var s=s_gi(s_account);
            s.trackingServer='Servername';
            s.pageName=window.location.pathname;
            s.t();
            alert('AppMeasurement script executed');
        """

        webView.evaluateJavaScript(appMeasurementInitialization) { (result, error) in
            if let error = error {
                print("Failed to inject initialization script: \(error.localizedDescription)")
            } else {
                print("Successfully injected initialization script")
            }
        }
    }

    // Handle JavaScript alerts
    func webView(_ webView: WKWebView, runJavaScriptAlertPanelWithMessage message: String, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping () -> Void) {
        print("JavaScript alert: \(message)")
        let alert = UIAlertController(title: nil, message: message, preferredStyle: .alert)
        alert.addAction(UIAlertAction(title: "OK", style: .default, handler: { _ in completionHandler() }))
        self.present(alert, animated: true, completion: nil)
    }

    // Allow JavaScript content
    func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, preferences: WKWebpagePreferences, decisionHandler: @escaping (WKNavigationActionPolicy, WKWebpagePreferences) -> Void) {
        preferences.allowsContentJavaScript = true
        decisionHandler(.allow, preferences)
    }
}

 

 

Thank you in advance for your assistance.

1 Reply

Avatar

Level 1

Fixed the issue. Following are the to do checks after the code updation

  • Enabled javascript to the initial code
  • Allowed arbitrary load
  • added local url to domains and updated the http exception

Updated code and plist

import UIKit
import WebKit

class ViewController: UIViewController, WKNavigationDelegate, WKUIDelegate {

    var webView: WKWebView!

    override func viewDidLoad() {
        super.viewDidLoad()

        // Configure WebView preferences
        let preferences = WKWebpagePreferences()
        preferences.allowsContentJavaScript = true
        
        let configuration = WKWebViewConfiguration()
        configuration.defaultWebpagePreferences = preferences
        let userContentController = WKUserContentController()
        
        // Inject AppMeasurement.js script
        if let appMeasurementScript = readAppMeasurementJS() {
            let userScript = WKUserScript(source: appMeasurementScript, injectionTime: .atDocumentEnd, forMainFrameOnly: false)
            userContentController.addUserScript(userScript)
        }
        
        configuration.userContentController = userContentController
        // Set up the WebView
        webView = WKWebView(frame: self.view.bounds, configuration: configuration)
        webView.navigationDelegate = self
        webView.uiDelegate = self
        webView.isInspectable = true
        webView.allowsBackForwardNavigationGestures = true
        webView.scrollView.isScrollEnabled = true
        self.view.addSubview(webView)

        // Load a URL
        if let url = URL(string: "local server") {
            let request = URLRequest(url: url)
            webView.load(request)
        }
    }
    private func readAppMeasurementJS() -> String? {
        if let filepath = Bundle.main.path(forResource: "AppMeasurement", ofType: "js") {
            do {
                let contents = try String(contentsOfFile: filepath)
                return contents
            } catch {
                print("Failed to read AppMeasurement.js")
                return nil
            }
        }
        return nil
    }
    // WKNavigationDelegate and WKUIDelegate methods
    func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
        print("Page finished loading")

        let appMeasurementInitialization = """
        try {
            var s_account=' account id';
            var s=s_gi(s_account);
            s.trackingServer='tracking server details';
            s.pageName=window.location.pathname;
            console.log('Adobe Analytics tracking script running');
            console.log('Tracking server:', s.trackingServer);
            console.log('Page name:', s.pageName);
            s.t();
            console.log('AppMeasurement script executed');
        } catch (e) {
            console.error('Error executing AppMeasurement script:', e);
            alert('Error executing AppMeasurement script: ' + e.message);
        }
        """
        
        webView.evaluateJavaScript(appMeasurementInitialization) { (result, error) in
            if let error = error {
                print("Failed to inject initialization script: \(error.localizedDescription)")
            } else {
                print("Successfully injected initialization script")
            }
        }
    }

    // Handle JavaScript alerts
    func webView(_ webView: WKWebView, runJavaScriptAlertPanelWithMessage message: String, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping () -> Void) {
        print("JavaScript alert: \(message)")
        let alert = UIAlertController(title: nil, message: message, preferredStyle: .alert)
        alert.addAction(UIAlertAction(title: "OK", style: .default, handler: { _ in completionHandler() }))
        self.present(alert, animated: true, completion: nil)
    }
    
    func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
        decisionHandler(.allow)
    }

}

 

plist

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>UIApplicationSceneManifest</key>
	<dict>
		<key>UIApplicationSupportsMultipleScenes</key>
		<false/>
		<key>UISceneConfigurations</key>
		<dict>
			<key>UIWindowSceneSessionRoleApplication</key>
			<array>
				<dict>
					<key>UISceneConfigurationName</key>
					<string>Default Configuration</string>
					<key>UISceneDelegateClassName</key>
					<string>$(PRODUCT_MODULE_NAME).SceneDelegate</string>
					<key>UISceneStoryboardFile</key>
					<string>Main</string>
				</dict>
			</array>
		</dict>
	</dict>
	<key>NSAppTransportSecurity</key>
	<dict>
		<key>NSAllowsArbitraryLoads</key>
		<true/>
		<key>NSExceptionDomains</key>
		<dict>
			<key>user.macbook-pro-6.local</key>
			<dict>
				<key>NSIncludesSubdomains</key>
				<true/>
				<key>NSExceptionAllowsInsecureHTTPLoads</key>
				<true/>
			</dict>
		</dict>
	</dict>
</dict>
</plist>