/
Deep Linking

Deep Linking

To create the best user experience, we should have the ability for customers to deep link into the chatbot based on domain or URL path and display corresponding peak view buttons and prompts. In addition if the user “starts over” they chatbot should use the deep link logic to restart to the correct flow.

To enable deep linking, we need to make sure we have the following components setup.

  • Settings

  • Intents

  • Experience Designer Logic

We have the ability to have stepped approach of determining the correct flow.

  • Do we have match for the current pages path?

    • If Yes, use corresponding flow id and prompt

    • If No, do we have match on the current domain?

      • If Yes, use corresponding flow id and prompt

      • If No, use the default launch flow id

Settings

In the settings schema we will have properties available for the following.

"domainToFlow": { "example.org": "64a563f99c5e1200815a303e", "my.example.org/PRD": "64d306d9709d4f007e435c70", "dev.example.org": "64a563f99c5e1200815a303e", "tools.orbita-cs.com": "64d306d9709d4f007e435c70" }, "pathToFlow": { "example.org/digital-medicine/connected-health/home-test-page": "64a626ad9c5e1200815a4974", "example.org/digitial_medicine/connected-health": "65a626ad9c5e1200815a4974", "example.org/digitial_medicine": "65a626ad9c5e1200815a4974", }, "flow": { "launch": { "id": "64a563f99c5e1200815a303e" }, . . . }

 

Intents

We will use the Amazon.StartOverIntent. This will correctly process if the user types “start over” or “startover”.

 

Experience Designer Logic

Launch

[ { "id": "1c2dd752.655129", "type": "function", "z": "81b0fb3a.94e8d8", "name": "Get project context", "func": "const orbitaUtil = global.get(\"orbitaUtil\");\nconst projectId = orbitaUtil.getProjectId(node);\n\nconst establishDeferral = () => {\n let deferred = null;\n \n const promise = new Promise((resolve, reject) => {\n deferred = {\n resolve,\n reject\n };\n });\n \n promise.deferred = deferred;\n \n return promise;\n};\n\nlet projects = global.get(\"projects\");\n\nif (!projects) {\n projects = {};\n global.set(\"projects\", projects);\n}\n\nflow.set(\"project\", undefined);\n\nlet project = projects[projectId];\n\nif (!project || project.isStale) {\n project = establishDeferral();\n projects[projectId] = project;\n}\n\nPromise.resolve(project).then((resolvedProject) => {\n flow.set(\"project\", resolvedProject);\n \n node.send(msg);\n});", "outputs": 1, "noerr": 0, "x": 290, "y": 140, "wires": [ [ "9292947b.0814e8" ] ] }, { "id": "9292947b.0814e8", "type": "function", "z": "81b0fb3a.94e8d8", "name": "Dependencies", "func": "const project = flow.get(\"project\");\n\nproject.awaitDependencies([\"baseIntents\", \"settings\", \"utilities\"]).then((resolvedDependencies) => {\n node.send(msg);\n}).catch((error) => {\n const moduleName = ORBI.utils.getFlowName(node);\n\n node.error(`${moduleName}: Dependency resolution failed: ${error}`);\n});", "outputs": 1, "noerr": 0, "x": 480, "y": 140, "wires": [ [ "c5606e97.f9751" ] ] }, { "id": "c5606e97.f9751", "type": "function", "z": "81b0fb3a.94e8d8", "name": "Custom afterLaunch handler", "func": "const orbitaUtil = global.get(\"orbitaUtil\");\n\nconst project = flow.get(\"project\");\n\nconst { baseIntents, utilities } = project;\n\nconst CUSTOM_DATA_PATHS = {\n ENTRY_POINT: \"payload.originalDetectIntentRequest.payload.customData.windowLocation.href\"\n};\n\nconst SETTINGS_PATHS = {\n PATH_TO_FLOW: \"pathToFlow\",\n DOMAIN_TO_FLOW: \"domainToFlow\"\n};\n\nbaseIntents.registerHandler(\"afterLaunch\", async (msg) => {\n const { settings } = project;\n \n let entryPoint = utilities.object.get(msg, CUSTOM_DATA_PATHS.ENTRY_POINT, null);\n \n if (entryPoint) {\n entryPoint = entryPoint.replace(/^http[s]?:\\/\\//i, \"\");\n \n const domain = entryPoint.split(\"/\")[0];\n \n const pathToFlow = utilities.object.get(settings, SETTINGS_PATHS.PATH_TO_FLOW, {});\n const domainToFlow = utilities.object.get(settings, SETTINGS_PATHS.DOMAIN_TO_FLOW, {});\n \n let launchFlowIdOverride = null;\n \n for (const path in pathToFlow){\n if (entryPoint.includes(path)) {\n launchFlowIdOverride = pathToFlow[path];\n }\n }\n \n if(!launchFlowIdOverride && domainToFlow[domain]){\n launchFlowIdOverride = domainToFlow[domain];\n }\n \n if (launchFlowIdOverride) {\n msg.launchFlowId = launchFlowIdOverride;\n } else {\n const _ = global.get('lodash');\n msg.menu = _.get(msg, 'payload.originalDetectIntentRequest.payload.customData.menu',null);\n if(msg.menu === 'unauthenticated'){\n msg.launchFlowId = utilities.object.get(settings, \"flow.unauthenticated.id\", null);\n } else if(msg.menu === 'authenticated'){\n msg.launchFlowId = utilities.object.get(settings, \"flow.authenticated.id\", null);\n }\n }\n \n if(msg.payload.originalDetectIntentRequest.payload.language){\n msg.orbita.session.language = msg.payload.originalDetectIntentRequest.payload.language;\n\n msg.payload.session.language = msg.orbita.session.language;\n msg.language = msg.orbita.session.language;\n msg.analytics.attributes = {\n 'lang': msg.language\n };\n }\n msg.orbita.session.visitID = orbitaUtil.uuid();\n }\n return msg;\n});", "outputs": 0, "noerr": 0, "x": 700, "y": 140, "wires": [] }, { "id": "4437498f.067e98", "type": "inject", "z": "81b0fb3a.94e8d8", "name": "", "topic": "", "payload": "", "payloadType": "date", "repeat": "", "crontab": "", "once": true, "onceDelay": 0.1, "x": 110, "y": 140, "wires": [ [ "1c2dd752.655129" ] ] }, { "id": "slots", "type": "slots", "z": "", "slots": [] } ]

Start Over

 

 

[ { "id": "c8319289.799db", "type": "alexa-http intent", "z": "34006a85.ab8eb6", "name": "", "skillConfig": "a765b69a.298f68", "url": "/alexa_test", "intent": "AMAZON.StartOverIntent", "lastIntent": "", "x": 340, "y": 1100, "wires": [ [ "b579c77c.7ba308" ] ] }, { "id": "cf3bf50c.e93cb8", "type": "alexa-http intent", "z": "34006a85.ab8eb6", "name": "", "skillConfig": "a765b69a.298f68", "url": "/alexa_test", "intent": "AMAZON.StartOverIntent", "lastIntent": "anystate", "x": 300, "y": 1140, "wires": [ [ "b579c77c.7ba308" ] ] }, { "id": "b579c77c.7ba308", "type": "function", "z": "34006a85.ab8eb6", "name": "Start Over Flow Picker", "func": "const orbitaUtil = global.get(\"orbitaUtil\");\n\nconst project = flow.get(\"project\");\n\nconst { baseIntents, utilities, settings, flowManager } = project;\n\nconst CUSTOM_DATA_PATHS = {\n ENTRY_POINT: \"payload.originalDetectIntentRequest.payload.customData.windowLocation.href\"\n};\n\nconst SETTINGS_PATHS = {\n PATH_TO_FLOW: \"pathToFlow\",\n DOMAIN_TO_FLOW: \"domainToFlow\"\n};\n\nvar launchFlowId = utilities.object.get(settings, \"flow.launch.id\", null); \n\n\nlet entryPoint = utilities.object.get(msg, CUSTOM_DATA_PATHS.ENTRY_POINT, null);\n \nif (entryPoint) {\n entryPoint = entryPoint.replace(/^http[s]?:\\/\\//i, \"\");\n \n const domain = entryPoint.split(\"/\")[0];\n \n const pathToFlow = utilities.object.get(settings, SETTINGS_PATHS.PATH_TO_FLOW, {});\n const domainToFlow = utilities.object.get(settings, SETTINGS_PATHS.DOMAIN_TO_FLOW, {});\n \n let launchFlowIdOverride = null;\n \n for (const path in pathToFlow){\n if (entryPoint.includes(path)) {\n launchFlowIdOverride = pathToFlow[path];\n }\n }\n \n if(!launchFlowIdOverride && domainToFlow[domain]){\n launchFlowIdOverride = domainToFlow[domain];\n }\n \n if (launchFlowIdOverride) {\n launchFlowId = launchFlowIdOverride;\n } else {\n const _ = global.get('lodash');\n msg.menu = _.get(msg, 'payload.originalDetectIntentRequest.payload.customData.menu',null);\n if(msg.menu === 'unauthenticated'){\n launchFlowId = utilities.object.get(settings, \"flow.unauthenticated.id\", null);\n } else if(msg.menu === 'authenticated'){\n launchFlowId = utilities.object.get(settings, \"flow.authenticated.id\", null);\n }\n }\n \n if(msg.payload.originalDetectIntentRequest.payload.language){\n msg.orbita.session.language = msg.payload.originalDetectIntentRequest.payload.language;\n\n msg.payload.session.language = msg.orbita.session.language;\n msg.language = msg.orbita.session.language;\n msg.analytics.attributes = {\n 'lang': msg.language\n };\n }\n msg.orbita.session.visitID = orbitaUtil.uuid();\n node.warn('flowid: ' + launchFlowId)\n}\n \nflowManager.changeFlow(msg, launchFlowId);\n\nreturn msg;\n", "outputs": 0, "noerr": 0, "x": 660, "y": 1120, "wires": [] }, { "id": "a765b69a.298f68", "type": "alexa-skill-config", "skillname": "Patient Access and Acquisition", "projectId": "647644399f8ae70079725b0e", "intents": "[]", "skillstate": "fromsession, flowManager, FPL, useSymptomChecker, escalation,flow, test,FlowStudio, testState, bill,escalation,confirm_escalation,help,emergency, Reminder, sanity, flow_stud,webWeight,fromSession,flowMngr,scheduleride,aMedication,Survey,whyhelpmessage,medication,callorcomeby,Januvia,survey2,glucose,faqquestion,DailySurveyInProgress,HeadacheSurveyInProgress,MonthlySurveyInProgress,FeedbackSurveyInProgress,AllReportsDone,AskedForChangeResponse,AskedForChangeTwice,MigraineTrackerQuestions1,MigraineTrackerQuestions2,MigraineTrackerQuestions3,StudyQuestions1,StudyQuestions2,StudyQuestions3,Help1,Help2,Help3,AskedForHeadacheStart,AskedForHeadacheStartYesterday,AskedForHeadacheStartTime,AskedForHeadacheEndTime,AskedForHeadacheTimeCorrectness,AskedForHeadacheChangeStartTime,AskedForHeadacheEndDate,InvalidHeadacheTime,AskedForContinuePartial,MaxRecognitionError,ServicePhoneNumber,ConfirmGoHome,ConfirmStop,ConfirmPause,ConfirmCancel,FORTESTING,testState,setup, startup, Survey,flowManager, survey, flowMngr,eventSurvey, whyhelpmessage, HeadacheSurveyInProgress, MonthlySurveyInProgress, FeedbackSurveyInProgress, AllReportsDone, AskedForChangeResponse, AskedForChangeTwice, MigraineTrackerQuestions1, MigraineTrackerQuestions2, MigraineTrackerQuestions3, StudyQuestions1, StudyQuestions2, StudyQuestions3, Help1, Help2, Help3, AskedForHeadacheStart, AskedForHeadacheStartYesterday, AskedForHeadacheStartTime, AskedForHeadacheEndTime, AskedForHeadacheTimeCorrectness, AskedForHeadacheChangeStartTime, AskedForHeadacheEndDate, InvalidHeadacheTime, AskedForContinuePartial, MaxRecognitionError, ServicePhoneNumber, ConfirmGoHome, ConfirmStop, ConfirmPause, ConfirmCancel,pain,dual,TreatmentSurgery,plateletsflow,password,changeappointmentList,MedicalHeart,chooseLocation,cancelAppointment,plateletsFlow, reminder, CheckUser, fromSession, plateletsFlow, cancelAppointment,PlateletsChangeOption,MedicalHemochromatosis, MedicalHeart,LifestyleSTD,setDateOrTimeIntent, FAQ,setTimelanding,setDatelanding,FAQ, fromsession, mayoKB, orbitaKB, askAnother, afterAssessment, phonePrompt, awaitingPhone, confirmPhone, finalPhonePrompt, inChunkedAnswer, appointmentPhonePrompt,reminder,CheckUser,Reminder,sanity,SymptomTriage,survey,LogHealthData,exampleCustomState,t0,t1,t2,t3, FAL, FAP,mayo,inFlow, mayo,flowStudio, resumePrompt,flow_stud", "disableLogging": false }, { "id": "slots", "type": "slots", "z": "", "slots": [] } ]

Related content

How to manage URL Params and Query strings
How to manage URL Params and Query strings
More like this
How do I configure Chatbot
How do I configure Chatbot
More like this
3.2.1 Launch Node
3.2.1 Launch Node
More like this
How to create an agent and link accounts in Google Dialogflow
How to create an agent and link accounts in Google Dialogflow
More like this
How to invoke an intent instead of Launch node on loading the chatbot
How to invoke an intent instead of Launch node on loading the chatbot
More like this
How to use Login Directive
How to use Login Directive
More like this