In App Navigation
9 min
deep linking & page navigation marketing configures a banner/floater/modal/etc in the appstorys dashboard with a cta link that's not a url — just a name like "productscreen" when a user taps it, the sdk hands that name to you via one line of code you write once you match the name to a screen and navigate import appstorys ios appstorys shared onnavigatetoscreen = { screenname in // screenname is whatever the dashboard cta was set to, e g "productscreen" router open(screenname) } that's the whole integration everything below explains the details, options, and edge cases why this exists campaigns often need a "shop now" or "view offer" button that opens a screen inside your app rather than a website the dashboard operator doesn't know your app's internal navigation code — they just type a screen name the sdk's job is to recognize "this isn't a website link" and pass that name back to your app; your app's job is to decide what "productscreen" actually means and navigate there this works exactly the same way whether the tap came from an in app campaign (banner, floater, modal, tooltip, widget, pip, csat, spin the wheel, survey), or a push notification the user tapped one handler, both sources nothing needs to be set up specially for either no setup, no navigation if you never register a handler, screen name links are silently ignored — they don't crash, block, or delay anything, including appstorys initialize() setting this up is entirely optional and can happen whenever it's convenient for you — you don't need it ready before initializing the sdk step 1 — register a handler (pick one) use one of these, not all three — they all receive the same information swiftui apps → use the closure import appstorys ios appstorys shared onnavigatetoscreen = { screenname in switch screenname { case "productscreen" router path append( product) case "cart" router path append( cart) default break // unknown name — ignore } } put this wherever your router/navigation state already lives — a good spot is onappear on your root view, or right after you create your router object uikit apps → use the delegate import appstorys ios final class appnavigationhandler appstorysnavigationdelegate { func appstorys( sdk appstorys, didrequestnavigationtoscreen screenname string, campaignid string?) { switch screenname { case "productscreen" coordinator showproduct() case "cart" coordinator showcart() default break } } } // keep a strong reference somewhere long lived (appdelegate/scenedelegate) — // the sdk only holds a weak reference, so if nothing else retains your // handler it will be deallocated and stop receiving events let navigationhandler = appnavigationhandler() appstorys shared navigationdelegate = navigationhandler prefer not to touch appstorys shared directly? use notificationcenter import appstorys ios notificationcenter default addobserver( forname appstorys didrequestscreennavigation, object nil, queue main ) { notification in guard let screenname = notification userinfo?\["screen"] as? string else { return } // navigate } good for modular apps where the navigation code lives in a different module than your sdk setup code step 2 — push notifications if you've already followed pushnotifcation guide md (calling appstorysmessagingservice handlenotificationclick(userinfo ) when a push is tapped), you're already done — no extra code needed push carries "deep link" "https //yourapp com/product/42" → opened as a website link, same as before push carries "deep link" "productscreen" (no https // , no custom scheme) → delivered to the exact same handler you registered in step 1 full working example — swiftui import swiftui import appstorys ios enum approute hashable { case product, cart, offers } final class router observableobject { @published var path = navigationpath() func route(for screenname string) { switch screenname { case "productscreen" path append(approute product) case "cart" path append(approute cart) case "offers" path append(approute offers) default break // unknown screen name from the dashboard — ignore } } } @main struct myapp app { @stateobject private var router = router() init() { appstorys initialize(accountid " ", appid " ", userid " ") } var body some scene { windowgroup { navigationstack(path $router path) { homeview() navigationdestination(for approute self) { route in switch route { case product productview() case cart cartview() case offers offersview() } } } onappear { appstorys shared onnavigatetoscreen = { screenname in router route(for screenname) } } } } } full working example — uikit import uikit import appstorys ios final class appcoordinator appstorysnavigationdelegate { private let navigationcontroller uinavigationcontroller init(navigationcontroller uinavigationcontroller) { self navigationcontroller = navigationcontroller appstorys shared navigationdelegate = self } func appstorys( sdk appstorys, didrequestnavigationtoscreen screenname string, campaignid string?) { switch screenname { case "productscreen" navigationcontroller pushviewcontroller(productviewcontroller(), animated true) case "cart" navigationcontroller pushviewcontroller(cartviewcontroller(), animated true) default break // unknown screen name from the dashboard — ignore } } } // in your scenedelegate, after setting up the window's root navigation controller var coordinator appcoordinator? // keep this alive for the app's lifetime func scene( scene uiscene, willconnectto session uiscenesession, options uiscene connectionoptions) { // create window + rootnavigationcontroller as usual coordinator = appcoordinator(navigationcontroller rootnavigationcontroller) } notes callbacks are always delivered on the main thread — safe to update ui/navigation directly inside them registering a handler is optional and order independent — it never blocks or delays sdk initialization