> For the complete documentation index, see [llms.txt](https://guide.xs2a.com/xs2a/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://guide.xs2a.com/xs2a/integration-cs/integration-variants/javascript-widget/javascript-widget-in-your-app.md).

# Webview App Integration

You can also integrate our Javascript-Widget solution inside a web-view in your mobile App(s).

The integration follows almost the same procedure as described in our description for [Javascript-Widget](https://app.gitbook.com/@fintecsystems/s/xs2a/~/drafts/-MVWf7ugWCabMOAFyIvI/integration-cs/integration-variants/javascript-widget).

{% hint style="warning" %}
Some special steps have to be taken when integrating the JS-Widget in a web-view, which will be described below in the examples.
{% endhint %}

## Implementation Steps for the Hosted Page Implementing the JS-Widget

You will need a HTML page that implements the JS-Widget, just like described in [Javascript-Widget](/xs2a/integration-cs/integration-variants/javascript-widget.md). In addition, the following changes are recommended:

### HTML

```markup
<!-- in the <head> -->
<!-- Scale settings so the page does not zoom/move-->
<meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no, maximum-scale=1.0, user-scalable=no">

```

### CSS

```css
#XS2A-Form input:not([type='checkbox']):not([type='radio']), #XS2A-Form select {
    /* Increase the font size for input elements, 16px minimum is recommended */
    font-size: 16px !important;
}
```

### JS-to-Native Callbacks

The most important steps to be taken are about handling the callbacks the JS-Widget does in your mobile app. For example, when the user finishes the process, you probably want to close the web-view and show the user a specific screen. The same needs to be done when the user aborts.

This can be accomplished with registering callbacks, that notify the host app (your app) from within the Javascript on the hosted page. You might already have callbacks defined such as `xs2a.finish()` or `xs2a.abort()` , for which you will need to add some more functionality:

```javascript
xs2a.finish(function () {
    if (window.App) {
        // Callback to native Android App
        App.finishTransaction();
    } else if (window.webkit) {
        // Callback to native iOS App
        webkit.messageHandlers.callback.postMessage("finished");
    }
});

xs2a.abort(function () {
    if (window.App) {
        // Callback to native Android App
        App.abortTransaction();
    } else if (window.webkit) {
        // Callback to native iOS App
        webkit.messageHandlers.callback.postMessage("aborted");
    }
});

xs2a.configure({
    // ESSENTIAL!
    // this needs to be set so that in-app webviews handle redirects properly
    'reuse-tab-on-redirect': true
});
```

## Implementation Steps for the Native Apps

In the app, we need some functionality to show the web-view and to deal with the callbacks defined above.

### iOS

The following is an example class showing an integration with WKWebView and how the JS-to-Native callbacks are defined and configured:

```swift
import UIKit
import WebKit

class WebViewController: UIViewController, WKNavigationDelegate, WKScriptMessageHandler, UIAdaptivePresentationControllerDelegate {
	var webView: WKWebView!
	var urlToLoad: URL!
	
	/* Capture Javascript Messages */
	func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
		guard let response = message.body as? String else { return }
		let storyboard = UIStoryboard(name: "Main", bundle: nil)
		var screenToPresent: UIViewController?
		
		if response == "finished" {
			/* The user finished the session */
			screenToPresent = storyboard.instantiateViewController(withIdentifier: "successView") as UIViewController
		} else if response == "aborted" {
			/* User pressed abort button */
			screenToPresent = storyboard.instantiateViewController(withIdentifier: "abortedView") as UIViewController
		}

		if let screenToPresent = screenToPresent {
			present(screenToPresent, animated: true, completion: nil)
		}
		
	}
	
	
	override func loadView() {
		let contentController = WKUserContentController()
		/* Register javascript-to-native callbacks */
		/* This lets us use "webkit.messageHandlers.callback.postMessage" in the JS */
		contentController.add(self, name: "callback")
		
		let config = WKWebViewConfiguration()
		config.userContentController = contentController
		
		let frame = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height)
		webView = WKWebView(frame: frame, configuration: config)
		webView.navigationDelegate = self
		view = webView
	}

	override func viewDidLoad() {
		super.viewDidLoad()
		self.presentationController?.delegate = self
		webView.load(URLRequest(url: urlToLoad!))
		webView.allowsBackForwardNavigationGestures = false
	}

	init(url: URL) {
		self.urlToLoad = url
		super.init(nibName: nil, bundle: nil)
	}
	
	required init?(coder: NSCoder) {
		super.init(coder: coder)
	}

	func presentationControllerDidDismiss(_ presentationController: UIPresentationController) {
		webView.removeFromSuperview()
		view = nil
	}
}

```

You can present this web-view like this:

```swift
let vc = WebViewController(url: <URL_TO_HOSTED_PAGE>)
self.present(vc, animated: true, completion: nil)
```

### Android

Register the JS-to-Native callbacks:

```java
import android.util.Log;
import android.webkit.JavascriptInterface;
import android.widget.Toast;

import androidx.navigation.fragment.NavHostFragment;

public class WebViewJSInterface {
    private static final String TAG = "WebViewJSInterface";

    SecondFragment fragment;

    public WebViewJSInterface(SecondFragment fragment) {
        this.fragment = fragment;
    }

    @JavascriptInterface
    public void finishTransaction() {
        Log.d(TAG, "finishTransaction: Finish Transaction on Android");
        
        // navigate to success screen
    }

    @JavascriptInterface
    public void abortTransaction() {
        Log.d(TAG, "finishTransaction: Abort Transaction on Android");

        // navigate to e.g. abort screen
    }
}
```

Configure and present the web-view:

```java
private void loadXS2AIntoWebView(@NonNull View view, String wizardSessionKey) {
    WebView webView = view.findViewById(R.id.main_web_view);
    webView.getSettings().setJavaScriptEnabled(true);
    // This lets use use window.App in the JS
    webView.addJavascriptInterface(new WebViewJSInterface(this), "App");
    webView.setWebViewClient(new WebViewClient() {
        public boolean shouldOverrideUrlLoading(WebView view, String url) {
            view.loadUrl(url);
            return true;
        }
    });

    webView.loadUrl(<URL_TO_HOSTED_PAGE>);
}
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://guide.xs2a.com/xs2a/integration-cs/integration-variants/javascript-widget/javascript-widget-in-your-app.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
