CustomerGlu Developer Documentation
  • 🔧Getting started
  • 🔧Quickstart Guide for React Web Apps
  • 📱Quickstart Guide for React Native Apps
  • 📱Quickstart Guide for Flutter Apps
  • Integrating with SDKs
    • Web SDK
    • Mobile SDKs
      • How to Test Integration?
    • Cordova SDK
    • Shopify
  • Integrating with APIs
    • Register User/Device
    • Load Campaigns
    • Binding Webview to Native App Functions
    • 🔍Using __GLU_NUDGE_CLICK for Widget Visibility
    • 🎯API-based Segmentation Quickstart Guide
  • 🔌Third-Party Integrations
    • Source
      • Sending Events directly from Server
      • Segment
      • Moengage
      • Amplitude
      • Clevertap
      • Webengage
    • Destination
      • Analytics Webhook
      • Customer.io
      • Talon.One
      • Segment
      • MoEngage
      • Amplitude
      • Clevertap
      • WebEngage
      • Google Sheets
    • Cohort
      • Mixpanel
  • Miscellaneous Topics
    • Direct Campaign/Wallet URLs
    • Configuring Webhooks
      • Rewards Webhook
      • Nudge Webhook
    • Notifications
      • FCM
      • APNs
      • CustomerGlu Notification
      • Testing Nudges
    • Referral Campaigns
      • Firebase
      • Branch
    • Handling Non Logged-in Users
    • Testing Campaigns with User Logs
    • Using the Editor
      • How to edit Buttons in Campaigns
    • How to Create and Manage Segments in CustomerGlu
  • SCHEMA REPOSITORY
    • Webhook Schema
      • Reward Webhook Schema
      • Nudge Webhook Schema
      • Raw Event Webhook Schema
    • Webview Callback Schema
      • Analytics Event Schema
    • Analytics schema V4
      • Page Events
      • Track Events (UI)
      • Track Events (SDK)
      • State-Change Events
      • System Events
    • 🗝️FAQ
      • API Key
      • How to find and add Screen Names for Entrypoints
  • Demo Apps
    • Demo Apps
Powered by GitBook
On this page
  • Binding Webview clicks to native code
  • EventJSON

Was this helpful?

  1. Integrating with APIs

Binding Webview to Native App Functions

Handling the interaction between webview programs and the app

PreviousIntegrating with APIsNextUsing __GLU_NUDGE_CLICK for Widget Visibility

Last updated 9 months ago

Was this helpful?

Binding Webview clicks to native code

The webview might want to access some native features. Like opening a deeplink, showing the share drawer, etc.

  • callback native method should be binded with any webview.

  • The webview will pass eventJSON to the callback function.

The webview will call this function in the following ways -

app.callback(eventJSON); //Android
webkit.messageHandlers.callback.postMessage(eventJSON); // iOS

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.util.Log;
import org.json.JSONObject;

public class MainActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        WebView webView = (WebView)findViewById(R.id.web_view);
        webView.loadUrl("https://app-markk.customerglu.com/program"); // webview url
        webView.getSettings().setJavaScriptEnabled(true);
        webView.addJavascriptInterface(new WebViewJavaScriptInterface(this), "app"); // **IMPORTANT** call it app
    }
    /*
     * JavaScript Interface. Web code can access methods in here
     * (as long as they have the @JavascriptInterface annotation)
     */
    public class WebViewJavaScriptInterface{
        private Context context;
        /*
         * Need a reference to the context in order to sent a post message
         */
        public WebViewJavaScriptInterface(Context context){
            this.context = context;
        }
        /*
         * This method can be called from Android. @JavascriptInterface
         * required after SDK version 17.
         */
        @JavascriptInterface
         // **IMPORTANT** call it callback
        public void callback(String message){
            JSONObject data = new JSONObject(message);
            // data has the event information
            Log.d(data);
        }
    }
}
import UIKit
import WebKit
import Foundation

class ViewController: UIViewController , WKScriptMessageHandler{
    @IBOutlet weak var mWebKitView: WKWebView!
    @IBOutlet weak var mEdtTxt: UITextField!
    var mNativeToWebHandler : String = "callback" // **IMPORTANT** call it callback
    var webviewUrl: String = "https://app-markk.customerglu.com/program" // webview url
    override func viewDidLoad() {
        super.viewDidLoad()
        let myURL = URL(string: webviewUrl)
        let myRequest = URLRequest(url: myURL!)
        mWebKitView.load(myRequest)
        let contentController = WKUserContentController()
        mWebKitView.configuration.userContentController = contentController
        mWebKitView.configuration.userContentController.add(self, name: mNativeToWebHandler)
    }

    // message handler
    func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
        if message.name == mNativeToWebHandler {
            // message.body holds JSON of the event
            let jsonMessageString: String = message.body as? String;
            let jsonDict = try JSONSerialization.jsonObject(with: jsonMessageString) as? NSDictionary
            // // jsonDict has the event information
            print(jsonDict)
        }
    }
}
package com.customerglu.kotlinwebviewnativecomm

import android.content.Context
import android.os.Bundle
import android.webkit.JavascriptInterface
import android.widget.Button
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import kotlinx.android.synthetic.main.activity_main.*

class MainActivity : AppCompatActivity() {

    // TODO: Replace url with the url for your program/campaign.
    private val url = "<Provide-Your-campaign-url here>"

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        exampleWebView.settings.javaScriptEnabled = true
        exampleWebView.addJavascriptInterface(JSComm(this),"app")
        exampleWebView.loadUrl(url)

    }

    /**
     * Receive message from webview
     */
    class JSComm(val context: Context){
        @JavascriptInterface
        fun callback(message:String){
            // Capture message from webview and print as toast
            Toast.makeText(context,message, Toast.LENGTH_LONG).show()
        }
    }

}
import React from "react";
import WebView, { WebViewMessageEvent } from "react-native-webview";
import { StyleSheet, Text, View } from "react-native";

export function GluWebView({ url }: { url: string }) {

  /* Callback for the WebView */
  function onWebViewEvent(event: WebViewMessageEvent) {
    const data: IWebViewEvent = JSON.parse(event.nativeEvent.data);
    console.log(data);
  }

  return (
    <View style={styles.container}>
      <WebView
        source={{ uri: url }}
        onMessage={onWebViewEvent} /* Pass the callback (line: 34) defined as props */
        renderLoading={() => (
          <Text style={styles.text}>Loading Webview...</Text>
        )}
        renderError={() => (
          <Text style={styles.text}>Error Loading Webview...</Text>
        )}
        startInLoadingState
        style={{ marginTop: 20 }}
      />
    </View>
  );
}

type IWebViewEvent = IOpenDeepLinkEvent | ICloseEvent | IShareEvent;

interface IOpenDeepLinkEvent {
  eventName: "OPEN_DEEPLINK";
  data: {
    deepLink: string;
    name: string;
  };
}

interface ICloseEvent {
  eventName: "CLOSE";
}

interface IShareEvent {
  eventName: "SHARE";
  data: {
    channelName: "WHATSAPP" | "SMS" | "EMAIL" | "OTHERS";
    text: string;
    image: string;
  };
}


const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: "#fff",
    alignItems: "stretch",
    justifyContent: "center",
  },
  text: {
    fontSize: 30,
  },
});

Flutter WebView 4.0 and above:

import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';

// Import for Android features.
import 'package:webview_flutter_android/webview_flutter_android.dart';
// Import for iOS features.
import 'package:webview_flutter_wkwebview/webview_flutter_wkwebview.dart';
class MyWebView extends StatefulWidget {
  @override
  WebState createState() => WebState();
}

class WebState extends State<MyWebView> {

  late final WebViewController _controller;

  @override
  void initState() {
    super.initState();

    // #docregion platform_features
    late final PlatformWebViewControllerCreationParams params;
    if (WebViewPlatform.instance is WebKitWebViewPlatform) {
      params = WebKitWebViewControllerCreationParams(
        allowsInlineMediaPlayback: true,
        mediaTypesRequiringUserAction: const <PlaybackMediaTypes>{},
      );
    } else {
      params = const PlatformWebViewControllerCreationParams();
    }

    final WebViewController controller =
    WebViewController.fromPlatformCreationParams(params);
    // #enddocregion platform_features

    controller
      ..setJavaScriptMode(JavaScriptMode.unrestricted)
      ..setBackgroundColor(const Color(0x00000000))
      ..setNavigationDelegate(
        NavigationDelegate(
          onProgress: (int progress) {
            debugPrint('WebView is loading (progress : $progress%)');
          },
          onPageStarted: (String url) {
            debugPrint('Page started loading: $url');
          },
          onPageFinished: (String url) {
            debugPrint('Page finished loading: $url');
          },
          onWebResourceError: (WebResourceError error) {
            debugPrint('''
Page resource error:
  code: ${error.errorCode}
  description: ${error.description}
  errorType: ${error.errorType}
  isForMainFrame: ${error.isForMainFrame}
          ''');
          },
          onNavigationRequest: (NavigationRequest request) {
            if (request.url.startsWith('https://www.youtube.com/')) {
              debugPrint('blocking navigation to ${request.url}');
              return NavigationDecision.prevent;
            }
            debugPrint('allowing navigation to ${request.url}');
            return NavigationDecision.navigate;
          },
          onHttpError: (HttpResponseError error) {
            debugPrint('Error occurred on page: ${error.response?.statusCode}');
          },
          onUrlChange: (UrlChange change) {
            debugPrint('url change to ${change.url}');
          },
          onHttpAuthRequest: (HttpAuthRequest request) {
          //  openDialog(request);
          },
        ),
      )
      ..addJavaScriptChannel(
        'app',
        onMessageReceived: (JavaScriptMessage message) {

            print("Handle Your navigation logic "+ message.message);
    
        },
      )
      ..loadRequest(Uri.parse('CAMPAIGN_URL'));

    // #docregion platform_features
    if (controller.platform is AndroidWebViewController) {
      AndroidWebViewController.enableDebugging(true);
      (controller.platform as AndroidWebViewController)
          .setMediaPlaybackRequiresUserGesture(false);
    }
    // #enddocregion platform_features

    _controller = controller;
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        body: SafeArea(
      top: true,
      child: WebViewWidget(controller: _controller,)
    ));
  }
}

Flutter WebView Below v4.0:

import 'package:webview_flutter/webview_flutter.dart';
class MyWebView extends StatefulWidget {
  @override
  WebState createState() => WebState();
}

class WebState extends State<MyWebView> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        body: SafeArea(
      top: true,
      child: WebView(   
        initialUrl: "CAMPAIGN_URL",    //Need to put Campaign url 
        javascriptMode: JavascriptMode.unrestricted,   //IMPORTANT for enablig javascript
        javascriptChannels: <JavascriptChannel>[
          JavascriptChannel(
              name: 'app', // Name is "app"
              onMessageReceived: (s) {
                print(s.message); // s.message contains event data like  {"eventName":"CLOSE","data":null}
              }),
        ].toSet(),
      ),
    ));
  }
}

EventJSON

  • The native callback function should be able to identify the event using eventName property present in the JSON.

  • The data property contains data relevant to that eventName.

Download Sample Kotlin App from our

Download Sample React Native App from our

Download Sample Flutter App from our

Check out all possible Webview events .

Github
Github
Github
here