Skip to main content

Browser-based iOS integration tutorial

If you have an iOS app built with Swift, here's a tutorial on how to add Ramp to it in just a few steps.

You can see the full code sample at


We recommend using the Ramp iOS SDK to integrate Ramp into your iOS app natively. See its documentation here.

What do we need to do?

  • compose a URL for the Ramp widget with parameters of your choice
  • create a Safari view controller and load the composed URL
  • [OPTIONAL] handle a callback URL to complete the purchase

In detail

Composing the widget URL

The Ramp widget allows you to provide some parameters before displaying it, so the user doesn't have to type or copy-paste information. You can set options such as wallet address, cryptocurrency and crypto amount, etc. In order to do so, we need to create a URL with proper query items as showcased in the snippet below. You can find the description of all available parameters in our documentation.

struct Configuration {
var swapAsset: String? = nil
var swapAmount: String? = nil
var fiatCurrency: String? = nil
var fiatValue: String? = nil
var userAddress: String? = nil
var hostLogoUrl: String? = nil
var hostAppName: String? = nil
var userEmailAddress: String? = nil
var url: String
var finalUrl: String? = nil
var hostApiKey: String? = nil

func composeUrl() -> URL {
var urlComponents = URLComponents(string: url)!

urlComponents.appendQueryItem(name: "variant", value: "webview-mobile") // Mandatory QueryItem for webview integrations
urlComponents.appendQueryItem(name: "swapAsset", value: swapAsset)
urlComponents.appendQueryItem(name: "swapAmount", value: swapAmount)
urlComponents.appendQueryItem(name: "fiatCurrency", value: fiatCurrency)
urlComponents.appendQueryItem(name: "fiatValue", value: fiatValue)
urlComponents.appendQueryItem(name: "userAddress", value: userAddress)
urlComponents.appendQueryItem(name: "hostLogoUrl", value: hostLogoUrl)
urlComponents.appendQueryItem(name: "hostAppName", value: hostAppName)
urlComponents.appendQueryItem(name: "userEmailAddress", value: userEmailAddress)
urlComponents.appendQueryItem(name: "finalUrl", value: finalUrl)
urlComponents.appendQueryItem(name: "hostApiKey", value: hostApiKey)

return urlComponents.url!

extension URLComponents {
/// Appends query item to components. If no query items present,
/// creates new list. If value is nil, does nothing.
mutating func appendQueryItem(name: String, value: String?) {
guard let value = value else { return }
if queryItems == nil { queryItems = [.init(name: name, value: value)] }
else { queryItems!.append(.init(name: name, value: value)) }

Presenting Safari web view with widget

We've composed the Ramp widget URL with all the parameters we need. The next step is to instantiate a SFSafariViewController, present it with the present() call and load the URL we just composed.

import UIKit
import SafariServices

class ViewController: UIViewController {

func showRampInstantWidget() {
var configuration = Configuration(url: "")
configuration.fiatCurrency = "EUR"
configuration.fiatValue = "2"
configuration.swapAsset = "BTC_BTC"
configuration.finalUrl = "rampexample://ramp.purchase.complete"

let url = configuration.composeUrl()
let rampVC = SFSafariViewController(url: rampWidgetUrl)
present(rampVC, animated: true)


[OPTIONAL] Handling a callback URL

One of the query items you can pass to the Ramp widget URL is finalUrl. If you do this, Ramp will redirect your users to this URL after the purchase is completed. You can use this mechanism to redirect the user back to your app, to detect purchase completion and perform some actions like dismissing the Safari view controller and notifying your user.

Step 1 - Define a redirection URL

Now, we need to register a URL scheme that's unique for our app. Usually, the best way is to simply use the app's name for this. If your app's name is RampExample, the scheme may be rampexample. Next, append a path that is unique for completing purchase via Ramp, for example ramp.purchase.complete.

Having these two, you can now define a value for the finalUrl parameter - it will be rampexample://ramp.purchase.complete.

Step 2 - Register URL scheme

Now, add a URL scheme to your app. You can do it using the Info tab for a specific target in Xcode or by manually editing the Info.plist file. If iOS ever tries to open an URL with your scheme, it will pass the URL to your app to handle it. You can find more details on how to add a custom URL scheme in Apple documentation.

<string>rampexample</string> <!--Put your app scheme here-->

Step 3 - Handling the callback

Now it's time to handle the URL callback inside your app. There are two methods to implement, depending on iOS version:

  • UIWindowSceneDelegate - func scene(_:, openURLContexts:)
  • UIApplicationDelegate - func application(_:, open:, options:) -> Bool

These methods will be called when the system detects that a user tried to open an URL that fits our scheme.

That's where our Safari view controller and setting the finalUrl parameter comes into play. After the purchase is completed and user taps the confirmation button, SafariViewController will try to open the URL. Since it fits our registered scheme, the methods described above will be triggered, so you can use them to dismiss your Safari view controller, notify the user and perform any task you want.

You can implement the methods above however you like, but what should suit most use cases, is to send a notification.

let rampUrlScheme = "rampexample"
let rampNotificationName = Notification.Name(rawValue: "ramp.callback.notification")

class SceneDelegate: UIResponder, UIWindowSceneDelegate {


func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
let urlContext = URLContexts.first,
let components = URLComponents(url: url, resolvingAgainstBaseURL: false),
let scheme = components.scheme,
scheme == rampUrlScheme
let notification = Notification(name: rampNotificationName, object: url, userInfo: nil)

Then, you can listen for the notification anywhere in the code and react accordingly.

forName: rampNotificationName, object: nil, queue: .main) { (notification) in
if let rampCallbackUrl = notification.object as? URL {
// do whatever you want

That's it - your app can now use Ramp to allow your users to buy crypto easily.


If you want to provide the best off-ramping (selling crypto) experience to your users, we recommend to take advantage of the Native Flow. Implementation of the native flow may be required in some native mobile apps. You can see more details here.