question

Alfred avatar image
Alfred asked

Is it possible to upsell after a purchase?

I was able to handle the "after purchase" event but I'm wondering if it's possible to invoke the upsell API within the handler since I'm getting a problem when doing it. Here's the working code:

const AfterPurchaseIntentHandler = {
    canHandle(handlerInput) {
        return handlerInput.requestEnvelope.request.type === 'Connections.Response';
    },
    handle(handlerInput) {
        return handlerInput.responseBuilder
            .speak(constants.Messages.REPROMPT)
            .reprompt(constants.Messages.REPROMPT)
            .getResponse();
    }
};

And here's the not working code:

// TODO: implement upsell properly
const AfterPurchaseIntentHandlerOld = {
    canHandle(handlerInput) {
        return handlerInput.requestEnvelope.request.type === 'Connections.Response';
    },
    handle(handlerInput) {
        const locale = handlerInput.requestEnvelope.request.locale;
        const ms = handlerInput.serviceClientFactory.getMonetizationServiceClient();

        return ms.getInSkillProducts(locale).then(function(res) {
            const productReferenceName = 'currency_eur';

            const entitledProducts = getAllEntitledProducts(res.inSkillProducts);

            console.log(`entitledProducts: ${JSON.stringify(entitledProducts)}`);

            const product_record = entitledProducts.filter(
                record => record.referenceName === productReferenceName
            );

            console.log(`product_record: ${JSON.stringify(product_record)}`);

            if (product_record.length > 0) {
                console.log('no upsell');

                // no upsell
                return handlerInput.responseBuilder
                    .speak(constants.Messages.REPROMPT)
                    .reprompt(constants.Messages.REPROMPT)
                    .getResponse();
            } else {
                console.log('do an upsell');

                // do an upsell
                return handlerInput.responseBuilder
                    .addDirective({
                        type: 'Connections.SendRequest',
                        name: 'Upsell',
                        payload: {
                            InSkillProduct: {
                                productId: getProductId(res.inSkillProducts, productReferenceName)
                            }
                        },
                        upsellMessage: 'This is my product...Do you want to know more?',
                        token: 'correlationToken'
                    })
                    .getResponse();
            }
        });
    }
};

Also, is it possible to trigger a specific intent handler (that will ask for an upsell) programmatically instead of always asking for a response?

alexa skills kitnodejsisp
6 comments
10 |5000

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

What does 'getAllEntitledProducts' function do, how it is implemented? Are you sure that it is returning a result? Can you try logging it out? If it returns a promise you need to await its results, by using async/await.

Other than that, it looks correct. If I may ask, why do you want to upsell after purchase? I don't think it is a good practice to keep user in purchase loop constantly until he buys something or just exits the skill.

0 Likes 0 ·

thanks for the feedback @RokasV. the 'getAllEntitledProducts' is a simple function that filters what the user already bought. Here's the implementation (it's not returning a Promise)

function getAllEntitledProducts(inSkillProductList) {
    return inSkillProductList.filter(record => record.entitled === 'ENTITLED');
}

The logic actually goes until the Connections.SendRequest with an Upsell type. However, it seems that after that, the whole skill just suddenly exits. Not sure if there's an extra step to handle an Upsell event.

Note that this is just a test code and I agree that we should not put customers on a purchase loop. I just want to see how the Upsell works. Also, even if I really intend to do an upsell after a purchase, I can add an additional logic like it will only happen 10% of the time.

0 Likes 0 ·

I'm not sure what are the other types for 'addDirective'. I wonder if its possible to redirect to another Intent.

0 Likes 0 ·

I tried doing this too but same result, the skill just exited.

} else {
    console.log('do an upsell');
    WhatCanIBuyIntentHandler.handle(handlerInput);
}

I can't understand why is that happening. Hope someone can explain what's special about the 'after purchase' event.

0 Likes 0 ·

Hmm, this is interesting. Does it come to the handler itself at all? If not, then there might be an issue that you registered your handler after some sort of catch all handler. Can you check that out?

Also another thing to keep in mind is that when 'connections response' comes, it goes through everything, including interceptors so some sort of issue might be there too. Don't forget, that in that case there are no session attributes too.

I also overlooked your another question, about upselling without asking user. There is a way how to do it:

   return responseBuilder
        .addDirective({
          type: 'Connections.SendRequest',
          name: 'Buy',
          payload: {
            InSkillProduct: {
              productId: productId,
            },
          },
          token: 'token',
        })
        .getResponse()

You have to specify exactly which product are you upselling, this way user will be asked straight away if he wants to buy your offered item or not.

And also, yeah, to call another handler from handler, you have to call its handle method, as you did in trying to fix the issue, which leads me to believe, that the issue might be somewhere else.

0 Likes 0 ·
Show more comments

0 Answers