Remove headache and speed up your integration by using our Widget to quickly and painlessly connect your users' accounts.

Terra offers a plug-and-play Widget solution, both for web and mobile applications, that provides a secure and optimised authentication process for each provider. The Widget is the smoothest way for users to connect their Fitness account within your application.


Sample Images

Permissions screen and provider select screenPermissions screen and provider select screen

Permissions screen and provider select screen


Code Snippets

Below are some examples on how to pull up a widget or authentication view in different mobile environments.




React Native

For React Native, you can integrate with our widget in your application using in-app browser packages. Note that using the built-in react-native-webview will cause authentication issues with some of the wearable providers.

Below are integration steps for Expo CLI and React Native CLI. Note that they use different packages and have different implementations.


Resources

Demo projects for both Expo CLI and React Native CLI are available on GitHub.


Installation

Use the following installation instructions:

  • Expo CLI: install expo-web-browser (further setup details here)
  • React Native CLI: install react-native-inappbrowser-reborn (further setup details here)

Generate Session ID

Before using the in-app browser, you must generate a Session ID to pass to your application from your backend (further details about generating a Session ID here.


Using the In-App Browser

In your application, let's create an openWidget function to initiate the in-app browser in your application

import InAppBrowser from 'react-native-inappbrowser-reborn';

const openWidget = async () => {
  try {
    const url =
      'https://widget.tryterra.co/session/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx';
    if (await InAppBrowser.isAvailable()) {
      const result = await InAppBrowser.openAuth(url, {
        // iOS Properties
        dismissButtonStyle: 'cancel',
        preferredBarTintColor: '#453AA4',
        preferredControlTintColor: 'white',
        readerMode: false,
        animated: true,
        modalPresentationStyle: 'fullScreen',
        modalTransitionStyle: 'coverVertical',
        modalEnabled: true,
        enableBarCollapsing: false,
        // Android Properties
        showTitle: true,
        toolbarColor: '#6200EE',
        secondaryToolbarColor: 'black',
        navigationBarColor: 'black',
        navigationBarDividerColor: 'white',
        enableUrlBarHiding: true,
        enableDefaultShare: true,
        forceCloseOnRedirection: false,
        // Specify full animation resource identifier(package:anim/name)
        // or only resource name(in case of animation bundled with app).
        animations: {
          startEnter: 'slide_in_right',
          startExit: 'slide_out_left',
          endEnter: 'slide_in_left',
          endExit: 'slide_out_right',
        },
        headers: {
          'my-custom-header': 'my custom header value',
        },
      });
      Alert.alert(JSON.stringify(result));
    } else Linking.openURL(url);
  } catch (error: any) {
    Alert.alert(error.message);
  }
};
import * as WebBrowser from "expo-web-browser";

const openWidget = async () => {
  // customize redirect URL to get results wanted
  let result: any = await WebBrowser.openBrowserAsync(
    "https://widget.tryterra.co/session/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
  );
  // do something with the result
};

Then it is possible to use the function in your application to trigger the in-app browser.

<View style={styles.container}>
    <Button title="Open Terra Widget" onPress={openWidget} />
</View>



Swift

We have created a demo application which uses our widget for authentication available on GitHub.


Using BetterSafariView

Using a public library called BetterSafariView for the SFSafariViewController class in Swift makes it easier to implement the authentication process with Widget. Find out more here.

struct TerraWidgetSessionCreateResponse:Decodable{
    var status: String = String()
    var url: String = String()
    var session_id: String = String()
}
//Generate Session ID -> URL (RECOMMENDED THAT THIS IS DONE ON THE BACKEND, THIS IS JUST FOR A DEMO)
func getSessionId() -> String{
    let session_url = URL(string: "https://api.tryterra.co/v2/auth/generateWidgetSession")
    var url = ""
    var request = URLRequest(url: session_url!)
    let requestData = ["reference_id": "testing", "providers" : "APPLE, GOOGLE, GARMIN", "language": "EN"]
    let group = DispatchGroup()
    let queue = DispatchQueue(label: "widget.Terra")
    let jsonData = try? JSONSerialization.data(withJSONObject: requestData)
    request.httpMethod = "POST"
    request.setValue("application/json", forHTTPHeaderField: "Accept")
    request.setValue("application/json", forHTTPHeaderField: "Content-Type")
    request.setValue("YOUR_DEV_ID", forHTTPHeaderField: "dev-id")
    request.setValue("YOUR_X_API_KEY", forHTTPHeaderField: "X-API-Key")
    request.httpBody = jsonData
    let task = URLSession.shared.dataTask(with: request) {(data, response, error) in
        if let data = data{
            let decoder = JSONDecoder()
            do{
                let result = try decoder.decode(TerraWidgetSessionCreateResponse.self, from: data)
                url = result.url
                group.leave()
            }
            catch{
                print(error)
            }
        }
    }
    group.enter()
    queue.async(group:group) {
        task.resume()
    }
    group.wait()
    return url
}

@State private var startingWebAuthenticationSession = false

 var body: some View {
    Button("Start WebAuthenticationSession") {
                    self.startingWebAuthenticationSession = true
                }
                .webAuthenticationSession(isPresented: $startingWebAuthenticationSession) {
                    WebAuthenticationSession(
                        url: URL(string: getSessionId())!,
                        callbackURLScheme: "tryterra"
                    ) { callbackURL, error in
                        if let callbackURL = callbackURL {
                            print(callbackURL.absoluteString)
                        }
                        if let error = error{
                            print(error)
                        }
                    }
                }
 }



Flutter

For Flutter, you can integrate with our widget using the in-app browser package flutter_web_browser. Note that using the webviews will cause authentication issues with some of the wearable providers.


Resources

A demo project is available on GitHub.


Installation

After setting up the flutter application, add the flutter_web_browser dependency to your pubsec.yaml and install using flutter pub get. More details about the package can be found here.


Generate Session ID

Before using the in-app browser, you must generate a Session ID to pass to your application from your backend (further details about generating a Session ID here ).


Using the In-App Browser

The following code snippet will open an in-app browser session and present the Terra widget session to the user.

openBrowserTab() async {
    FlutterWebBrowser.openWebPage(
      url: "https://widget.tryterra.co/session/xxxx-xxxx-xxxx-xxxx-xxxx",
      customTabsOptions: const CustomTabsOptions(
        colorScheme: CustomTabsColorScheme.dark,
        toolbarColor: Colors.deepPurple,
        secondaryToolbarColor: Colors.green,
        navigationBarColor: Colors.amber,
        shareState: CustomTabsShareState.on,
        instantAppsEnabled: true,
        showTitle: true,
        urlBarHidingEnabled: true,
      ),
      safariVCOptions: const SafariViewControllerOptions(
        barCollapsingEnabled: true,
        preferredBarTintColor: Colors.green,
        preferredControlTintColor: Colors.amber,
        dismissButtonStyle: SafariViewControllerDismissButtonStyle.close,
        modalPresentationCapturesStatusBarAppearance: true,
      ),
    );
}