> ## Documentation Index
> Fetch the complete documentation index at: https://documentation.qonversion.io/llms.txt
> Use this file to discover all available pages before exploring further.

# No-code Screens

Leverage Qonversion's drag-and-drop mobile screen builder to build beautiful paywalls and onboarding flows. Increase user-to-trial, user-to-paid conversion rates, customer engagement and your app's revenue.

With Qonversion's remote no-code screens, you can:

1. Build a single screen (e.g. paywall)
2. Build a sequence of connected screens (e.g. onboarding)
3. Track user actions like button clicks with your product analytics
4. Edit screens' content remotely

## 1) Create a single screen

You can quickly create a beautiful paywall and other types of in-app screens with the Qonversion no-code screen builder. Follow <a href="/docs/single-screen" target="_blank" rel="noopener">this guide</a> to learn the details of building the in-app screen similar to the examples below.

<img src="https://mintcdn.com/qonversion/SziPfnpjOpZSUj1s/images/docs/f4b0fe9-Frame_1000001836_1.png?fit=max&auto=format&n=SziPfnpjOpZSUj1s&q=85&s=3056055d7fa8cae38cfd424622660d3c" alt="" width="7828" height="2959" data-path="images/docs/f4b0fe9-Frame_1000001836_1.png" />

## 2. Create a sequence of screens

You can build a set of no-code screens using the guide above and link them into a sequence.\
Simply connect your no-code screens using <a href="/docs/actions#4-navigate-to-the-screen" target="_blank" rel="noopener">Navigate to the screen</a> action in the screen builder.

Here is a short tutorial describing the sequence creation process:

<Embed url="https://www.youtube.com/watch?v=TmbL-nkiR08" href="https://www.youtube.com/watch?v=TmbL-nkiR08" html="%3Ciframe%20class%3D%22embedly-embed%22%20src%3D%22%2F%2Fcdn.embedly.com%2Fwidgets%2Fmedia.html%3Fsrc%3Dhttps%253A%252F%252Fwww.youtube.com%252Fembed%252FTmbL-nkiR08%253Ffeature%253Doembed%26display_name%3DYouTube%26url%3Dhttps%253A%252F%252Fwww.youtube.com%252Fwatch%253Fv%253DTmbL-nkiR08%26image%3Dhttps%253A%252F%252Fi.ytimg.com%252Fvi%252FTmbL-nkiR08%252Fhqdefault.jpg%26key%3Df2aa6fc3595946d0afc3d76cbbd25dc3%26type%3Dtext%252Fhtml%26schema%3Dyoutube%22%20width%3D%22854%22%20height%3D%22480%22%20scrolling%3D%22no%22%20title%3D%22YouTube%20embed%22%20frameborder%3D%220%22%20allow%3D%22autoplay%3B%20fullscreen%22%20allowfullscreen%3D%22true%22%3E%3C%2Fiframe%3E" />

## 3. Present a no-code screen

To present a no-code screen:

1. Copy the screen's ID from the Qonversion dashboard

<img src="https://mintcdn.com/qonversion/zdjn3kzNygqtFGgE/images/docs/acd764f-Screen_ID.png?fit=max&auto=format&n=zdjn3kzNygqtFGgE&q=85&s=15deafa21613a96f90e220bebab3df2d" alt="" width="3446" height="806" data-path="images/docs/acd764f-Screen_ID.png" />

2. Pass the ID to the following SDK method:

```swift theme={null}
Qonversion.Automations.shared().showScreen(withID: "screen_id_from_the_dashboard") { success, error in
    // handle success result or error here
}
```

```objectivec theme={null}
[[QONAutomations sharedInstance] showScreenWithID:@"screen_id_from_the_dashboard" completion:^(BOOL success, NSError * _Nullable error) {
    // handle success result or error here
}];
```

```java theme={null}
Automations.getSharedInstance().showScreen("screen_id_from_the_dashboard", new QonversionShowScreenCallback() {
    @Override
    public void onSuccess() {
        // handle success here
    }

    @Override
    public void onError(@NonNull QonversionError error) {
        // handle error here
    }
});
```

```kotlin theme={null}
Automations.shared.showScreen("screen_id_from_the_dashboard", callback = object: QonversionShowScreenCallback {
    override fun onSuccess() {
        // handle success here
    }

    override fun onError(error: QonversionError) {
        // handle error here
    }
})
```

```javascript Flutter theme={null}
try {
  await Automations.getSharedInstance().showScreen("screen_id_from_the_dashboard");
} catch (e) {
  // handle error here
}
```

```javascript React Native theme={null}
try {
  await Automations.getSharedInstance().showScreen('screen_id_from_the_dashboard');
} catch (e) {
  // handle error here
}
```

```csharp Unity theme={null}
Automations.GetSharedInstance().ShowScreen("screen_id_from_the_dashboard", error =>
{
    if (error != null)
    {
        // handle error here
    }
});
```

```typescript Cordova theme={null}
try {
  await Qonversion.Automations.getSharedInstance().showScreen('screen_id_from_the_dashboard');
} catch (e) {
  // handle error here
}
```

3. Call this method in any part of your app and enjoy remotely manageable no-code screens!

## 4) Customize screen presentation

You can configure with what animation a no-code screen should be presented. It works differently for native SDKs (iOS and Android) and for cross-platform SDKs. Let's have a look at them in turn.

Below are the minimal required SDK versions supporting this feature:

| Platform     | Minimal version |
| :----------- | :-------------- |
| iOS          | 3.1.0           |
| Android      | 4.1.0           |
| React Native | 4.1.0           |
| Flutter      | 5.1.0           |
| Unity        | 4.1.0           |

For iOS and Android, you should provide a `ScreenCustomizationDelegate`, which will be called each time before showing a no-code screen.

> 🚧
>
> We use a weak reference to the provided delegate to protect against memory leaks, so ensure that your delegate will remain alive as long as you need it (keep the reference to it somewhere in your code).

```swift theme={null}
// set the delegate somewhere in your code and keep the reference
Qonversion.Automations.shared().setScreenCustomizationDelegate(self)

...

// implement the function to return screen presentation configuration
func presentationConfigurationForScreen(_ screenId: String) -> Qonversion.ScreenPresentationConfiguration {
    return Qonversion.ScreenPresentationConfiguration(presentationStyle: .popover, animated: true)
}
```

```objectivec theme={null}
// set the delegate somewhere in your code and keep the reference
[[QONAutomations sharedInstance] setScreenCustomizationDelegate:self];

...
  
// implement the function to return screen presentation configuration
- (QONScreenPresentationConfiguration *)presentationConfigurationForScreen:(NSString *)screenId {
    return [[QONScreenPresentationConfiguration alloc] initWithPresentationStyle:QONScreenPresentationStylePopover animated:YES];
}
```

```java theme={null}
// implement the delegate to return screen presentation configuration
// do not forget to keep the reference on this object
private final ScreenCustomizationDelegate screenCustomizationDelegate = new ScreenCustomizationDelegate() {
    @NonNull
    @Override
    public QScreenPresentationConfig getPresentationConfigurationForScreen(@NonNull String screenId) {
        if (screenId.equals("screen_id_from_the_dashboard")) {
          	// return configuration for the concrete screen 
            return new QScreenPresentationConfig(QScreenPresentationStyle.NoAnimation);
        }
        
      	// return default configuration for all the rest screens
        return new QScreenPresentationConfig(QScreenPresentationStyle.FullScreen);
    }
};

...
  
// set the delegate somewhere in your code
Automations.getSharedInstance().setScreenCustomizationDelegate(screenCustomizationDelegate);
```

```kotlin theme={null}
// implement the delegate to return screen presentation configuration
// do not forget to keep the reference on this object
private val screenCustomizationDelegate = object : ScreenCustomizationDelegate {
	  override fun getPresentationConfigurationForScreen(screenId: String): QScreenPresentationConfig {
      	if (screenId === "screen_id_from_the_dashboard") {
        		// return configuration for the concrete screen 
          	return QScreenPresentationConfig(QScreenPresentationStyle.NoAnimation)
        }

        // return default configuration for all the rest screens
      	return QScreenPresentationConfig(QScreenPresentationStyle.FullScreen)
    }
}

...

// set the delegate somewhere in your code
Automations.shared.setScreenCustomizationDelegate(screenCustomizationDelegate)
```

In cross-platform SDKs, for that purpose, you should call the `setScreenPresentationConfig` method and provide a presentation configuration along with an identifier of a screen (optional) to which it should be applied. You can omit screen ID, and the provided configuration will be used for all no-code screens.

```javascript Flutter theme={null}
var config = new QScreenPresentationConfig(QScreenPresentationStyle.fullScreen, true);
// Set configuration for all screens.
Automations.getSharedInstance().setScreenPresentationConfig(config);
// Set configuration for the concrete screen.
Automations.getSharedInstance().setScreenPresentationConfig(config, "screen_id_from_the_dashboard");
```

```javascript React Native theme={null}
const config = new ScreenPresentationConfig(ScreenPresentationStyle.FULL_SCREEN, true);
// Set configuration for all screens.
Automations.getSharedInstance().setScreenPresentationConfig(config);
// Set configuration for the concrete screen.
Automations.getSharedInstance().setScreenPresentationConfig(config, 'screen_id_from_the_dashboard');
```

```csharp Unity theme={null}
ScreenPresentationConfig config = new ScreenPresentationConfig(ScreenPresentationStyle.FullScreen, true);
// Set configuration for all screens.
Automations.GetSharedInstance().SetScreenPresentationConfig(config);
// Set configuration for the concrete screen.
Automations.GetSharedInstance().SetScreenPresentationConfig(config, "screen_id_from_the_dashboard");
```

```typescript Cordova theme={null}
const config = new Qonversion.ScreenPresentationConfig(Qonversion.ScreenPresentationStyle.FULL_SCREEN, true);
// Set configuration for all screens.
Qonversion.Automations.getSharedInstance().setScreenPresentationConfig(config);
// Set configuration for the concrete screen.
Qonversion.Automations.getSharedInstance().setScreenPresentationConfig(config, 'screen_id_from_the_dashboard');
```

> 🚧 Call order matters
>
> Note that the `setScreenPresentationConfig` call order matters. So if you call it for the concrete screen first and then for all the screens (without providing screen ID), the first call will be overridden.

The `ScreenPresentationConfig` class consists of the following fields:

<table>
  <thead>
    <tr>
      <th>
        Field
      </th>

      <th>
        Type
      </th>

      <th>
        Description
      </th>
    </tr>
  </thead>

  <tbody>
    <tr>
      <td>
        `presentationStyle`
      </td>

      <td>
        `ScreenPresentationStyle`
        (default - `Push` for Android,
        `fullScreen` for iOS)
      </td>

      <td>
        Describes how screens will be displayed.
      </td>
    </tr>

    <tr>
      <td>
        `animated`
      </td>

      <td>
        boolean (default - `true`)
      </td>

      <td>
        iOS only. A flag that enables/disables screen presentation animation.
        For Android consider using `ScreenPresentationStyle.NoAnimation`
      </td>
    </tr>
  </tbody>
</table>

`ScreenPresentationStyle` is an enumeration of the <a href="/docs/screen-presentation-style-examples" target="_blank" rel="noopener">following variants</a>:

<table>
  <thead>
    <tr>
      <th>
        Variant
      </th>

      <th>
        iOS description
      </th>

      <th>
        Android description
      </th>
    </tr>
  </thead>

  <tbody>
    <tr>
      <td>
        Popover
      </td>

      <td>
        `UIModalPresentationPopover` analog. <a href="/docs/screen-presentation-style-examples#popover" target="_blank" rel="noopener">Example</a>.
      </td>

      <td>
        Not available for Android
      </td>
    </tr>

    <tr>
      <td>
        Push
      </td>

      <td>
        Not a modal representation. Pushes a controller to a current navigation stack.

        NavigationController on the top of the stack is required.

        <a href="/docs/screen-presentation-style-examples#push" target="_blank" rel="noopener">Example</a>.
      </td>

      <td>
        Default screen transaction animation on Android.

        <a href="/docs/screen-presentation-style-examples#push-1" target="_blank" rel="noopener">Example</a>.
      </td>
    </tr>

    <tr>
      <td>
        FullScreen
      </td>

      <td>
        `UIModalPresentationFullScreen` analog. <a href="/docs/screen-presentation-style-examples#fullscreen" target="_blank" rel="noopener">Example</a>.
      </td>

      <td>
        A screen moves from bottom to top. <a href="/docs/screen-presentation-style-examples#fullscreen-1" target="_blank" rel="noopener">Example</a>.
      </td>
    </tr>

    <tr>
      <td>
        NoAnimation
      </td>

      <td>
        Not available for iOS. For iOS consider providing `animated` flat to `QScreenPresentationConfig`
      </td>

      <td>
        A screen appears/disappears without any animation. <a href="/docs/screen-presentation-style-examples#noanimation" target="_blank" rel="noopener">Example</a>.
      </td>
    </tr>
  </tbody>
</table>

> 🚧 Cross-platform attention
>
> Please pay attention that the `Push` screen presentation style for iOS requires the navigation controller in the current stack of your application views. To use the `Push` presentation style, you must ensure your top-level view stack has `UINavigationController`. Otherwise, the no-code screen will not be presented.

## 5. Track no-code screen user clicks with analytics

In case you want to log button clicks or action results, add an <a href="/docs/handle-automations-result" target="_blank" rel="noopener">Automations delegate</a> to receive callbacks with the required information about users' behaviour.
