Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added a method for feedback widget segmentation #438

Merged
merged 13 commits into from
Nov 9, 2023
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
## 23.6.3
- You can now add segmentation while presenting a widget with 'present_feedback_widget'

## 23.6.2
- Adding app version information to every request

Expand Down
84 changes: 37 additions & 47 deletions examples/examples_feedback_widgets.html
Original file line number Diff line number Diff line change
Expand Up @@ -30,30 +30,27 @@
}

// Decide which which widget to show. Here the first rating widget is selected.
var i = countlyPresentableFeedback.length - 1;
var countlyFeedbackWidget = countlyPresentableFeedback[0];
while (i--) {
// You can change 'rating' to 'nps' or 'survey'. Or you can create your own logic here.
if (countlyPresentableFeedback[i].type === 'rating') {
countlyFeedbackWidget = countlyPresentableFeedback[i];
break;
}
const widgetType = "rating";
const countlyFeedbackWidget = countlyPresentableFeedback.find(widget => widget.type === widgetType);
if (!countlyFeedbackWidget) {
console.error(`[Countly] No ${widgetType} widget found`);
return;
}

// Define the element ID and the class name (optional)
var selectorId = "";
var selectorClass = "";
const selectorId = "";
const selectorClass = "";

// Define the segmentation (optional)
const segmentation = { page: "home_page" };

// Display the feedback widget to the end user
Countly.present_feedback_widget(countlyFeedbackWidget, selectorId, selectorClass);
Countly.present_feedback_widget(countlyFeedbackWidget, selectorId, selectorClass, segmentation);
}


//=================================================
// Fetching and reporting feedback widgets manually
//=================================================
var CountlyFeedbackWidget;
var CountlyWidgetData;
// an example of getting the widget list, using it to get widget data and then recording data for it manually. widgetType can be 'nps', 'survey' or 'rating'
function getFeedbackWidgetListAndDoThings(widgetType) {
// get the widget list
Expand All @@ -66,43 +63,36 @@
}

// find the widget object with the given widget type. This or a similar implementation can be used while using fetchAndDisplayWidget() as well
var i = feedbackList.length - 1;
while (i--) {
if (feedbackList[i].type === widgetType) {
CountlyFeedbackWidget = feedbackList[i];
break;
}
const countlyFeedbackWidget = feedbackList.find(widget => widget.type === widgetType);
if (!countlyFeedbackWidget) {
console.error(`[Countly] No ${widgetType} widget found`);
return;
}

// if the widget object is found
if (CountlyFeedbackWidget) {
// Get data with the widget object
Countly.getFeedbackWidgetData(CountlyFeedbackWidget,
// callback function, 1st param is the feedback widget data
function (feedbackData, err) {
if (err) { // error handling
console.log(err);
return;
}

CountlyWidgetData = feedbackData;
// record data according to the widget type
if (CountlyWidgetData.type === 'nps') {
Countly.reportFeedbackWidgetManually(CountlyFeedbackWidget, CountlyWidgetData, { rating: 3, comment: "comment" });
} else if (CountlyWidgetData.type === 'survey') {
var widgetResponse = {};
// form the key/value pairs according to data
widgetResponse["answ-" + CountlyWidgetData.questions[0].id] = CountlyWidgetData.questions[0].type === "rating" ? 3 : "answer";
Countly.reportFeedbackWidgetManually(CountlyFeedbackWidget, CountlyWidgetData, widgetResponse);
} else if (CountlyWidgetData.type === 'rating') {
Countly.reportFeedbackWidgetManually(CountlyFeedbackWidget, CountlyWidgetData, { rating: 3, comment: "comment", email: "email", contactMe: true });
}
// Get data with the widget object
Countly.getFeedbackWidgetData(CountlyFeedbackWidget,
// callback function, 1st param is the feedback widget data
function (feedbackData, err) {
if (err) { // error handling
console.error(err);
return;
}

);
} else {
console.error("The widget type you are looking for does not exist")
}
const CountlyWidgetData = feedbackData;
// record data according to the widget type
if (CountlyWidgetData.type === 'nps') {
Countly.reportFeedbackWidgetManually(CountlyFeedbackWidget, CountlyWidgetData, { rating: 3, comment: "comment" });
} else if (CountlyWidgetData.type === 'survey') {
var widgetResponse = {};
// form the key/value pairs according to data
widgetResponse["answ-" + CountlyWidgetData.questions[0].id] = CountlyWidgetData.questions[0].type === "rating" ? 3 : "answer";
Countly.reportFeedbackWidgetManually(CountlyFeedbackWidget, CountlyWidgetData, widgetResponse);
} else if (CountlyWidgetData.type === 'rating') {
Countly.reportFeedbackWidgetManually(CountlyFeedbackWidget, CountlyWidgetData, { rating: 3, comment: "comment", email: "email", contactMe: true });
}
}

);
})
}
</script>
Expand Down
20 changes: 17 additions & 3 deletions lib/countly.js
Original file line number Diff line number Diff line change
Expand Up @@ -3064,11 +3064,14 @@
/**
* Present the feedback widget in webview
* @param {Object} presentableFeedback - Current presentable feedback
* @param {String} id - DOM id to append the feedback widget
* @param {String} className - Class name to append the feedback widget
* @param {String} [id] - DOM id to append the feedback widget (optional, in case not used pass undefined)
* @param {String} [className] - Class name to append the feedback widget (optional, in case not used pass undefined)
* @param {Object} [feedbackWidgetSegmentation] - Segmentation object to be passed to the feedback widget (optional)
* */
this.present_feedback_widget = function(presentableFeedback, id, className) {
this.present_feedback_widget = function(presentableFeedback, id, className, feedbackWidgetSegmentation) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in case "id" and "class name" are not used, what value should be provided. should be mentioned in the function doc

// TODO: feedbackWidgetSegmentation implementation only assumes we want to send segmentation data. Change it if we add more data to the custom object.
log(logLevelEnums.INFO, "present_feedback_widget, Presenting the feedback widget by appending to the element with ID: [ " + id + " ] and className: [ " + className + " ]");

if (!this.check_consent(featureEnums.FEEDBACK)) {
return;
}
Expand All @@ -3081,6 +3084,12 @@
return;
}

log(logLevelEnums.INFO, "present_feedback_widget, Adding segmentation to feedback widgets:[" + JSON.stringify(feedbackWidgetSegmentation) + "]");
if (!feedbackWidgetSegmentation || typeof feedbackWidgetSegmentation !== "object" || Object.keys(feedbackWidgetSegmentation).length === 0) {
log(logLevelEnums.DEBUG, "present_feedback_widget, Segmentation is not an object or empty");
feedbackWidgetSegmentation = null;
}

try {
var url = this.url;

Expand Down Expand Up @@ -3125,6 +3134,11 @@
url += "&platform=" + this.platform;
url += "&app_version=" + this.app_version;
url += "&sdk_version=" + SDK_VERSION;
if (feedbackWidgetSegmentation) {
var customObjectToSendWithTheWidget = {};
customObjectToSendWithTheWidget.sg = feedbackWidgetSegmentation;
url += "&custom=" + JSON.stringify(customObjectToSendWithTheWidget);
}
// Origin is passed to the popup so that it passes it back in the postMessage event
// Only web SDK passes origin and web
url += "&origin=" + passedOrigin;
Expand Down
Loading