Docs
grovs.io Start for free

Deep linking

Handle incoming deep links and SDK errors in your Unity game with the Grovs SDK.

Subscribe to Grovs.DeeplinkReceived for link payloads and Grovs.ErrorOccurred for SDK failures. Both run on the Unity main thread.

C#
using GrovsSDK;
using UnityEngine;
 
public class LinkRouter : MonoBehaviour
{
    void OnEnable() => Grovs.DeeplinkReceived += OnDeeplink;
    void OnDisable() => Grovs.DeeplinkReceived -= OnDeeplink;
 
    void OnDeeplink(GrovsDeeplink deeplink)
    {
        // Data is never null. Whole numbers arrive as long on both platforms.
        if (deeplink.Data.TryGetValue("level", out var level))
            LoadLevel((long)level);
 
        Debug.Log("Link: " + deeplink.Link + ", from push: " + deeplink.FromPush);
        if (deeplink.Tracking != null) Debug.Log("Campaign: " + deeplink.Tracking.Campaign);
    }
 
    void LoadLevel(long level) { /* your scene loading */ }
}

The event fires for universal links and App Links, the URI scheme, deferred deep links after an install, links from Grovs push notifications, and links passed to HandleUrl.

GrovsDeeplink fields:

FieldTypeDescription
LinkstringThe opened link. Can be null.
DataIReadOnlyDictionary<string, object>The link's custom payload. Never null, empty when there's none.
TrackingGrovsTrackingCampaign, Source and Medium. Can be null.
FromPushbooltrue when the link came from a Grovs push notification.
RawJsonstringThe message as the native bridge sent it.

Payload values are JSON types: string, bool, long for whole numbers, double for other numbers, null, lists and Dictionary<string, object>.

The native SDK starts before Unity, so a link can arrive before your scripts run. Links that arrive with no subscriber are kept, up to 20, and delivered in order to the first subscriber. Later subscribers don't get them. Subscribe early, for example in your first scene.

Grovs.LastDeeplink holds the most recent link, or null.

To open a Grovs link tapped in your own UI, a chat message say:

C#
bool handled = Grovs.HandleUrl("https://x.sqd.link/abc");
  • The URL must be absolute with a scheme and a host. Anything else throws ArgumentException, and null throws ArgumentNullException.
  • Returns false while Grovs is disabled.
  • The result arrives in DeeplinkReceived like any other link.

Handling SDK errors

C#
Grovs.ErrorOccurred += error => Debug.LogWarning("Grovs: " + error.Code + " " + error.Message);

ErrorOccurred carries errors that have no other place to be reported. Failed Tasks and callbacks carry their own error.

PlatformWhat ErrorOccurred reports
iOSEvery asynchronous native SDK error: authentication, network, event dispatch, link generation and in-app display failures
AndroidIn-app message failures and bridge errors only

Codes are listed under GrovsErrorCode. Errors are informational: the native SDK retries on its own.

Clipboard-assisted deferred deep linking

When a copy-to-clipboard link opens in a browser, the preview page copies it before sending the player to the store. On the first launch after install, the SDK reads it and attributes the install deterministically. The deferred link arrives in DeeplinkReceived, like a fingerprint match.

No code is needed. If your links use a custom domain, add it to Clipboard domains in Project Settings. Grovs-owned hosts are always accepted.

PlatformBehavior
iOSThe system paste prompt may show on first launch. Denying it leaves the install unattributed.
AndroidReading the clipboard needs window focus. It works because Grovs starts before the activity.

Turn it on per link with CopyToClipboardIos / CopyToClipboardAndroid, or set the project default in the dashboard. Flow and limits: Copy to Clipboard. How the check runs on iOS: iOS deep linking.

Read a link's details by its path:

C#
try
{
    IReadOnlyDictionary<string, object> details = await Grovs.GetLinkDetailsAsync("/abc");
    foreach (var pair in details) Debug.Log(pair.Key + ": " + pair.Value);
}
catch (GrovsException e)
{
    Debug.LogWarning("Details failed: " + e.Error);
}

Or with a callback:

C#
Grovs.GetLinkDetails("/abc", (details, error) =>
{
    if (error != null) Debug.LogWarning(error);
    else Debug.Log(details.Count + " fields");
});

A null path throws ArgumentNullException. The dictionary holds the fields the backend returns for the link.

  1. Open Grovs → Simulate Deep Link.
  2. Enter Play Mode.
  3. Type a link and a JSON object for the data, for example {"level": 3}.
  4. Press Send.

DeeplinkReceived fires exactly as it would for a real link, with Tracking set to null. Use it to test routing code without a device. Everything else in the Editor goes to a stub that does nothing.

See also

Last updated 2026-10-26
Was this page helpful?