Links
A link to a place in your app opens the app on a phone that has it, and a web page or the app store on one that does not: from an email, a QR code on a table, a text message. Each app has its own links, and its test app its own again.
A link is your app’s path under its link base:
- on PurrCRM‘s own host:
https://app.purrcrm.com/l/<your app's link name>/<path>, which needs nothing but the settings below; or - on a host of your own, such as
https://go.northwind.example/<path>, whose DNS points at PurrCRM.
/offers/42 in your app is then <link base>/offers/42. PurrCRM‘s own pages are in the same space, such as <link base>/messages/tickets/<id>.
1. Settings
Section titled “1. Settings”On Settings › Channels › Links (an owner or admin):
- Name: your app’s part of PurrCRM‘s host (
northwind), or a host of its own. A host of your own needs a DNS record (a CNAME to PurrCRM‘s host); the tab checks it, and your PurrCRM administrator then adds the host. - iOS apps:
<Apple team id>.<bundle id>, such asABCDE12345.com.northwind.app. - Android package and Android signing SHA-256: your
applicationId, and the SHA-256 of every certificate the app is signed with (from Play Console › App integrity, plus your upload and debug keys:keytool -list -v -keystore <file>). - Optionally a web page for a phone without the app (
{path}in it is the link’s path), and your App Store and Google Play pages. Without them, a phone without the app gets a page in your brand with “Open in Northwind” and the stores. - Use these links in emails, once most phones run a build with step 2.
PurrCRM then serves the files phones read to trust your app with the links (/.well-known/apple-app-site-association and /.well-known/assetlinks.json). Check what phones read fetches both as a phone does. The tab also shows the snippets below, filled in for your app.
2. In the app
Section titled “2. In the app”Android, in the activity that opens links (AndroidManifest.xml):
<intent-filter android:autoVerify="true"> <action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.BROWSABLE" /> <data android:scheme="https" android:host="crm.example.com" android:pathPrefix="/l/northwind/" /></intent-filter>Use your PurrCRM host as android:host (or your own host, with no pathPrefix). On iOS, add the Associated Domains capability (Runner.entitlements):
<key>com.apple.developer.associated-domains</key><array> <string>applinks:crm.example.com</string></array>A debug build may write applinks:crm.example.com?mode=developer, with developer mode on in the phone’s settings, so iOS reads the file afresh. Associated Domains needs a paid Apple team.
3. Hand the facade every link
Section titled “3. Hand the facade every link”Before your own handling, give the facade every link the phone hands you. handleLink answers whether the link was PurrCRM‘s; it then goes where it names once a user is signed in and ready, as a tapped push does. With the app_links package:
final appLinks = AppLinks();
Future<void> openLink(Uri link) async { if (await crm.handleLink(link)) return; // Your own links (a product, a referral...), as before.}
final initial = await appLinks.getInitialLink();if (initial != null) unawaited(openLink(initial));appLinks.uriLinkStream.listen(openLink);An email’s link the app opened counts as the email’s click, and every link is recorded as a link_opened event for segments and goals.
4. Declare your places
Section titled “4. Declare your places”Declare the places a link may go, so your team picks them in PurrCRM‘s link picker instead of typing paths:
CrmHost( followable: (link) => link.startsWith('/offers') || link == '/wallet' ? link : null, openInApp: router.go, links: const [ CrmLink(name: 'Offer page', path: '/offers/{offer_id}', screen: 'offer'), CrmLink(name: 'All offers', path: '/offers?category={category}'), CrmLink(name: 'Wallet', path: '/wallet', screen: 'wallet'), ],)A part in braces is filled in by whoever writes the link: a value, or an attribute such as {{first_name}}. webUrl is the place’s page on the web. The app sends the list once per build, and your team finds it under Settings › Channels › Links › Destinations. Declaring a place opens nothing: followable still decides.
5. Name your screens
Section titled “5. Name your screens”Call crm.screen('wallet') as each screen shows (the same name every time; never a path or an id). Your team can then show an in-app message only on some screens. With go_router:
router.routerDelegate.addListener(() { final name = screenNameOf(router.routerDelegate.currentConfiguration.uri.path); if (name != null) crm.screen(name);});