/// <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();
    }
示例#3
0
    /// <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();
    }
示例#4
0
    /// <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");
        }
    }
示例#5
0
 /// <summary>
 /// Gets winning variant of the test.
 /// </summary>
 private ABVariantInfo GetTestWinner()
 {
     return(ABVariants.FirstOrDefault(v => v.ABVariantGUID == ABTest.ABTestWinnerGUID));
 }
示例#6
0
    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);
    }