Skip to content

Instantly share code, notes, and snippets.

@tygavin
Last active November 4, 2019 18:41
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tygavin/5a0ccae21995067d79ff0edd633058d6 to your computer and use it in GitHub Desktop.
Save tygavin/5a0ccae21995067d79ff0edd633058d6 to your computer and use it in GitHub Desktop.
Shows how to call tealium.track inside and Amazon Alexa skill
// IMPORTANT:
// Please update the ##ACCOUNT## and ##PROFILE## values below to match your Tealium account and profile names
// This sample demonstrates handling intents from an Alexa skill using the Alexa Skills Kit SDK (v2).
// Please visit https://alexa.design/cookbook for additional examples on implementing slots, dialog management,
// session persistence, api calls, and more.
const Alexa = require('ask-sdk-core');
const https = require('https');
const crypto = require('crypto');
const hash = crypto.createHash('sha256');
const LaunchRequestHandler = {
canHandle(handlerInput) {
return Alexa.getRequestType(handlerInput.requestEnvelope) === 'LaunchRequest';
},
handle(handlerInput) {
const speakOutput = 'Welcome, say "send data to you" to record an event in Tealium.';
const attributesManager = handlerInput.attributesManager;
const sessionAttributes = attributesManager.getSessionAttributes() || {};
// At launch, store the visitorId (hashed userId) in Session Storage
hash.update(handlerInput.requestEnvelope.context.System.user.userId);
sessionAttributes.visitorId = hash.digest('hex');
attributesManager.setSessionAttributes(sessionAttributes);
return handlerInput.responseBuilder
.speak(speakOutput)
.reprompt(speakOutput)
.getResponse();
}
};
// Example shows how to use a tealium.track call inside a handler
const DataHubIntentHandler = {
canHandle(handlerInput) {
return Alexa.getRequestType(handlerInput.requestEnvelope) === 'IntentRequest'
&& Alexa.getIntentName(handlerInput.requestEnvelope) === 'DataHubIntent';
},
handle(handlerInput) {
const speakOutput = 'Thank you for sending data to Tealium!';
const sessionAttributes = handlerInput.attributesManager.getSessionAttributes();
// Fire off event data collection (tealium.track will POST data to Tealium Collect API endpoint)
tealium.track("alexa_skill_used", {
alexa_app_id: handlerInput.requestEnvelope.context.System.application.applicationId,
alexa_user_id: sessionAttributes.visitorId,
alexa_intent: Alexa.getIntentName(handlerInput.requestEnvelope),
timestamp: handlerInput.requestEnvelope.request.timestamp,
locale: handlerInput.requestEnvelope.request.locale,
viewport_width: handlerInput.requestEnvelope.context.Viewport.currentPixelWidth,
viewport_height: handlerInput.requestEnvelope.context.Viewport.currentPixelHeight
});
return handlerInput.responseBuilder
.speak(speakOutput)
//.reprompt('add a reprompt if you want to keep the session open for the user to respond')
.getResponse();
}
};
const tealium = {
account: '##ACCOUNT##',
profile: '##PROFILE##',
datasource: '##DATASOURCE##',
track: function(eventName, dataLayer) {
var req,
httpsConfig,
eventData;
// We are assuming dataLayer is valid JSON Object
dataLayer.tealium_account = tealium.account,
dataLayer.tealium_profile = tealium.profile,
dataLayer.tealium_datasource = tealium.datasource,
dataLayer.tealium_event = eventName;
eventData = JSON.stringify(dataLayer);
httpsConfig = {
hostname: 'collect.tealiumiq.com',
port: 443,
method: 'POST',
path: '/event',
headers: {
'Content-Type': 'application/json',
'Content-Length': eventData.length
}
}
req = https.request(httpsConfig, (res) => {
if (res.statusCode !== 200) {
console.log('Tealium Collect endpoint responded with status: ' + res.statusCode)
}
});
req.on('error', (error) => {
console.log(error);
});
req.write(eventData);
req.end();
}
};
const HelloWorldIntentHandler = {
//...
};
const HelpIntentHandler = {
//...
};
const CancelAndStopIntentHandler = {
//...
};
const SessionEndedRequestHandler = {
//...
};
// The intent reflector is used for interaction model testing and debugging.
// It will simply repeat the intent the user said. You can create custom handlers
// for your intents by defining them above, then also adding them to the request
// handler chain below.
const IntentReflectorHandler = {
canHandle(handlerInput) {
return Alexa.getRequestType(handlerInput.requestEnvelope) === 'IntentRequest';
},
handle(handlerInput) {
const intentName = Alexa.getIntentName(handlerInput.requestEnvelope);
const speakOutput = `You just triggered ${intentName}`;
return handlerInput.responseBuilder
.speak(speakOutput)
//.reprompt('add a reprompt if you want to keep the session open for the user to respond')
.getResponse();
}
};
// Generic error handling to capture any syntax or routing errors. If you receive an error
// stating the request handler chain is not found, you have not implemented a handler for
// the intent being invoked or included it in the skill builder below.
const ErrorHandler = {
canHandle() {
return true;
},
handle(handlerInput, error) {
console.log(`~~~~ Error handled: ${error.stack}`);
const speakOutput = `Sorry, I had trouble doing what you asked. Please try again.`;
return handlerInput.responseBuilder
.speak(speakOutput)
.reprompt(speakOutput)
.getResponse();
}
};
// The SkillBuilder acts as the entry point for your skill, routing all request and response
// payloads to the handlers above. Make sure any new handlers or interceptors you've
// defined are included below. The order matters - they're processed top to bottom.
exports.handler = Alexa.SkillBuilders.custom()
.addRequestHandlers(
DataHubIntentHandler,
LaunchRequestHandler,
HelloWorldIntentHandler,
HelpIntentHandler,
CancelAndStopIntentHandler,
SessionEndedRequestHandler,
IntentReflectorHandler, // make sure IntentReflectorHandler is last so it doesn't override your custom intent handlers
)
.addErrorHandlers(
ErrorHandler,
)
.lambda();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment