/// <summary> /// Initializes unigrid. /// </summary> private void InitializeGrid() { gridElem.DataSource = new InfoDataSet <ABVariantDataInfo>(ABVariants.ToArray()); gridElem.GridView.AddCssClass("rows-middle-vertical-align"); if (!DataAvailable(VariantsStatisticsData.Values, drpSuccessMetric.SelectedValue)) { columnConversionsOverVisits.Visible = false; } if (drpSuccessMetric.SelectedValue == METRIC_CONVERSION_VALUE) { columnConversionValue.Visible = true; // Hide chance to beat original and conversion rate interval columns as they are related to conversion rate HideChanceToBeatAndRateColumns(); } else if (drpSuccessMetric.SelectedValue == METRIC_AVG_CONVERSION_VALUE) { columnAvgConversionValue.Visible = true; // Hide chance to beat original and conversion rate interval columns as they are related to conversion rate HideChanceToBeatAndRateColumns(); } if (ValidationHelper.GetString(drpConversions.SelectedValue, "") == "") { // Hide chance to beat original and conversion rate interval columns as they don't provide relevant data when all conversions are selected HideChanceToBeatAndRateColumns(); if (drpSuccessMetric.SelectedValue == METRIC_CONVERSION_RATE) { columnImprovement.Visible = false; } } // If Visitors conversion methodology selected, use "Visitors" instead of "Visits" in unigrid if (drpCountingMethodology.SelectedValue == ABTestConstants.ABSESSIONCONVERSION_FIRST) { columnConversionsOverVisits.Caption = GetString("abtesting.conversionsovervisitors"); } }
/// <summary> /// Selects variant as winner. /// </summary> /// <param name="winnerGuid">Winner variant GUID</param> private void SelectWinner(Guid winnerGuid) { if (winnerGuid == Guid.Empty || OriginalVariant == null) { ShowError(GetString("abtesting.pushwinner.error.general")); return; } var variant = ABVariants.FirstOrDefault(v => v.ABVariantGUID == winnerGuid); if (variant == null) { ShowError(GetString("abtesting.pushwinner.error.general")); return; } if (!UserHasPermissions || !DocumentManager.AllowSave) { ShowError(GetString("abtesting.pushwinner.error.general")); return; } // Set winner GUID to ABTest ABTest.ABTestWinnerGUID = variant.ABVariantGUID; using (var transaction = new CMSTransactionScope()) { abTestManager.PromoteVariant(DocumentManager.Node, variant.ABVariantGUID); DocumentManager.SaveDocument(); transaction.Commit(); } DisplayWinnerInformation(variant); // Reload data because HeaderActions_ActionPerformed event is too late to change action tooltip gridElem.ReloadData(); // Reload summary box based on new status LoadSummaryBox(); }
/// <summary> /// Finishes test and selects variant as winner. /// </summary> /// <param name="winnerName">Winner variant name</param> private void FinishTestAndSelectVariantAsWinner(string winnerName) { if (String.IsNullOrEmpty(winnerName) || (OriginalVariant == null)) { ShowError(GetString("abtesting.pushwinner.error.general")); return; } var variant = ABVariants.FirstOrDefault(v => v.ABVariantName == winnerName); if (variant == null) { ShowError(GetString("abtesting.pushwinner.error.general")); return; } // Set winner GUID to ABTest ABTest.ABTestWinnerGUID = variant.ABVariantGUID; // If the test is running, finish it if (TestStatus == ABTestStatusEnum.Running) { ABTest.ABTestOpenTo = DateTime.Now; } ABTestInfoProvider.SetABTestInfo(ABTest); DisplayWinnerInformation(variant); SetWinnerTooltip(); // Reload data because HeaderActions_ActionPerformed event is too late to change action tooltip gridElem.ReloadData(); // Reload summary box based on new status LoadSummaryBox(); }
/// <summary> /// Initializes unigrid. /// </summary> private void InitializeGrid() { gridElem.DataSource = new InfoDataSet <ABVariantInfo>(ABVariants.ToArray()); if (drpSuccessMetric.SelectedValue == "conversionvalue") { columnConversionValue.Visible = true; // Hide chance to beat original and conversion rate interval columns as they are related to conversion rate HideChanceToBeatAndRateColumns(); } else if (drpSuccessMetric.SelectedValue == "averageconversionvalue") { columnAvgConversionValue.Visible = true; // Hide chance to beat original and conversion rate interval columns as they are related to conversion rate HideChanceToBeatAndRateColumns(); } if (ValidationHelper.GetString(drpConversions.Value, "") == "") { // Hide chance to beat original and conversion rate interval columns as they don't provide relevant data when all conversions are selected HideChanceToBeatAndRateColumns(); if (drpSuccessMetric.SelectedValue == "conversionrate") { columnImprovement.Visible = false; } } // If Visitors conversion methodology selected, use "Visitors" instead of "Visits" in unigrid if (drpCountingMethodology.SelectedValue == "absessionconversionfirst") { columnConversionsOverVisits.Caption = GetString("abtesting.conversionsovervisitors"); } }
/// <summary> /// Gets winning variant of the test. /// </summary> private ABVariantInfo GetTestWinner() { return(ABVariants.FirstOrDefault(v => v.ABVariantGUID == ABTest.ABTestWinnerGUID)); }
protected object gridElem_OnExternalDataBound(object sender, string sourceName, object parameter) { if (!RequestHelper.IsPostBack()) { return(string.Empty); } // Handle the grid action first because it doesn't require access to VariantsStatisticsData if (sourceName == "selectwinner") { var gridViewRow = parameter as GridViewRow; if (gridViewRow != null) { var dataRowView = gridViewRow.DataItem as DataRowView; if (dataRowView != null) { var img = sender as CMSGridActionButton; if (img != null) { // Check permissions to select winner if (!IsUserAuthorizedToManageTest) { img.Enabled = false; img.ToolTip = GetString("abtesting.selectwinner.permission.tooltip"); } else { var winner = GetTestWinner(); if (winner != null) { string variantName = (ValidationHelper.GetString(dataRowView["ABVariantName"], "")); if (variantName == winner.ABVariantName) { // Disable action image for the winning variant img.Enabled = false; } else { // Hide action image for other variants img.Visible = false; } } } } } } return(string.Empty); } string currentVariantName = parameter.ToString(); if (String.IsNullOrEmpty(currentVariantName) || (OriginalVariant == null) || !VariantsStatisticsData.ContainsKey(currentVariantName)) { return(string.Empty); } var variantData = VariantsStatisticsData[currentVariantName]; switch (sourceName) { case "name": var variant = ABVariants.FirstOrDefault(v => v.ABVariantName == currentVariantName); if (variant != null) { var link = new HtmlAnchor(); link.InnerText = ResHelper.LocalizeString(variant.ABVariantDisplayName); link.HRef = DocumentURLProvider.GetUrl(variant.ABVariantPath); link.Target = "_blank"; return(link); } break; case "conversionsovervisits": return(variantData.ConversionsCount + " / " + variantData.Visits); case "chancetobeatoriginal": if ((currentVariantName != OriginalVariant.ABVariantName) && (VariantPerformanceCalculator != null) && (variantData.Visits > 0)) { double chanceToBeatOriginal = VariantPerformanceCalculator.GetChanceToBeatOriginal(variantData.ConversionsCount, variantData.Visits); // Check whether the variant is most probably winning already and mark the row green if ((chanceToBeatOriginal >= WINNING_VARIANT_MIN_CHANCETOBEAT) && (variantData.ConversionsCount >= WINNING_VARIANT_MIN_CONVERSIONS)) { AddCSSToParentControl(sender as WebControl, "winning-variant-row"); } return(String.Format("{0:P2}", chanceToBeatOriginal)); } break; case "conversionrate": if ((VariantPerformanceCalculator != null) && (variantData.Visits > 0) && ABConversionRateIntervals.ContainsKey(currentVariantName) && ABConversionRateIntervals.ContainsKey(OriginalVariant.ABVariantName)) { // Render the picture representing how the challenger variant is performing against the original variant return(new ABConversionRateIntervalVisualizer( mMinConversionRateLowerBound, mConversionRateRange, ABConversionRateIntervals[currentVariantName], ABConversionRateIntervals[OriginalVariant.ABVariantName])); } break; case "conversionvalue": return(variantData.ConversionsValue); case "averageconversionvalue": return(String.Format("{0:#.##}", variantData.AverageConversionValue)); case "improvement": if ((currentVariantName != OriginalVariant.ABVariantName) && VariantsStatisticsData.ContainsKey(OriginalVariant.ABVariantName)) { var originalData = VariantsStatisticsData[OriginalVariant.ABVariantName]; switch (drpSuccessMetric.SelectedValue) { case "conversioncount": if (!originalData.ConversionsCount.Equals(0)) { return(GetPercentageImprovementPanel((variantData.ConversionsCount / (double)originalData.ConversionsCount) - 1)); } break; case "conversionvalue": if (!originalData.ConversionsValue.Equals(0)) { return(GetPercentageImprovementPanel((variantData.ConversionsValue / originalData.ConversionsValue) - 1)); } break; case "conversionrate": if (!originalData.ConversionRate.Equals(0)) { return(GetPercentageImprovementPanel((variantData.ConversionRate / originalData.ConversionRate) - 1)); } break; case "averageconversionvalue": if (!originalData.AverageConversionValue.Equals(0)) { return(GetPercentageImprovementPanel((variantData.AverageConversionValue / originalData.AverageConversionValue) - 1)); } break; } } break; } return(string.Empty); }
protected object gridElem_OnExternalDataBound(object sender, string sourceName, object parameter) { // Handle the grid action first because it doesn't require access to VariantsStatisticsData if (sourceName == "selectwinner") { if (parameter is GridViewRow gridViewRow && gridViewRow.DataItem is DataRowView dataRowView) { var action = sender as CMSAccessibleButtonBase; var variantGuid = ValidationHelper.GetGuid(dataRowView["ABVariantGUID"], Guid.Empty); InitializeGridAction(action, variantGuid); } return(string.Empty); } var currentVariantGuid = ValidationHelper.GetGuid(parameter, Guid.Empty); if (currentVariantGuid == Guid.Empty || (OriginalVariant == null) || !VariantsStatisticsData.ContainsKey(currentVariantGuid)) { return(string.Empty); } var variantData = VariantsStatisticsData[currentVariantGuid]; switch (sourceName) { case "name": var variant = ABVariants.FirstOrDefault(v => v.ABVariantGUID == currentVariantGuid); if (variant != null) { return(HTMLHelper.HTMLEncode(ResHelper.LocalizeString(variant.ABVariantDisplayName))); } break; case METRIC_CONVERSIONS_OVER_VISITS: return(variantData.ConversionsCount + " / " + variantData.Visits); case METRIC_CHANCE_TO_BEAT_ORIGINAL: if ((currentVariantGuid != OriginalVariant.ABVariantGUID) && (VariantPerformanceCalculator != null) && (variantData.Visits > 0)) { double chanceToBeatOriginal = VariantPerformanceCalculator.GetChanceToBeatOriginal(variantData.ConversionsCount, variantData.Visits); // Check whether the variant is most probably winning already and mark the row green if ((chanceToBeatOriginal >= WINNING_VARIANT_MIN_CHANCETOBEAT) && (variantData.ConversionsCount >= WINNING_VARIANT_MIN_CONVERSIONS)) { AddCSSToParentControl(sender as WebControl, "winning-variant-row"); } return(String.Format("{0:P2}", chanceToBeatOriginal)); } break; case METRIC_CONVERSION_RATE: if ((VariantPerformanceCalculator != null) && (variantData.Visits > 0) && ABConversionRateIntervals.ContainsKey(currentVariantGuid) && ABConversionRateIntervals.ContainsKey(OriginalVariant.ABVariantGUID)) { // Render the picture representing how the challenger variant is performing against the original variant return(new ABConversionRateIntervalVisualizer( mMinConversionRateLowerBound, mConversionRateRange, ABConversionRateIntervals[currentVariantGuid], ABConversionRateIntervals[OriginalVariant.ABVariantGUID])); } break; case METRIC_CONVERSION_VALUE: return(variantData.ConversionsValue); case METRIC_AVG_CONVERSION_VALUE: return(String.Format("{0:#.##}", variantData.AverageConversionValue)); case "improvement": if ((currentVariantGuid != OriginalVariant.ABVariantGUID) && VariantsStatisticsData.ContainsKey(OriginalVariant.ABVariantGUID)) { var originalData = VariantsStatisticsData[OriginalVariant.ABVariantGUID]; switch (drpSuccessMetric.SelectedValue) { case METRIC_CONVERSION_COUNT: if (!originalData.ConversionsCount.Equals(0)) { return(GetPercentageImprovementPanel((variantData.ConversionsCount / (double)originalData.ConversionsCount) - 1)); } break; case METRIC_CONVERSION_VALUE: if (!originalData.ConversionsValue.Equals(0)) { return(GetPercentageImprovementPanel((variantData.ConversionsValue / originalData.ConversionsValue) - 1)); } break; case METRIC_CONVERSION_RATE: if (!originalData.ConversionRate.Equals(0)) { return(GetPercentageImprovementPanel((variantData.ConversionRate / originalData.ConversionRate) - 1)); } break; case METRIC_AVG_CONVERSION_VALUE: if (!originalData.AverageConversionValue.Equals(0)) { return(GetPercentageImprovementPanel((variantData.AverageConversionValue / originalData.AverageConversionValue) - 1)); } break; } } break; } return(string.Empty); }