Public Backlog

WebinOne announcements, releases, updates and achievements

v6.11 Release date: 07 Feb, 2024

Full Release Notes

BACKLOG

Zapier - trigger recurring subscription change

Create a new trigger for the subscription change event

Name: Updated Recurring Subscription
Logic: Trigger event each time subscription status is changed

`RecurringSubscription` response object:

    {
        "Code": "Sub_123",
        "Status": "Canceled",
        "MemberId": 11111,
        "RecurringProducts": [
            {
                "EntityType": "SecureZoneSubscription",
                "Id": 1,
                "Name": "SZ"
            }
        ]
    }

Status values:

  • Incomplete
  • IncompleteExpired
  • Trialing
  • Active
  • PastDue
  • Canceled
  • Unpaid

EntityType values:

  • Form
  • ModuleItem
  • SecureZoneSubscription

Extension: Meta Conversion API Integration

1) Add extension Meta Conversion API Integration

Name: Meta Conversion API Integration (beta)
Short Description: Utilizes Meta Events via the Conversion API.
Price: Free during the beta period
Design: https://invis.io/E813E62LNS7H 

Supported the following events:

  • Add to cart
  • Initiate checkout
  • Complete registration
  • Lead
  • Purchase

More info can be found here:

- https://www.facebookblueprint.com/student/activity/212738-connect-your-data-with-pixel-and-conversions-api

- https://developers.facebook.com/docs/marketing-api/conversions-api/get-started

2) Extension page in Admin

Add page to extension menu item

Name: Meta Conversion API Integration

Design: https://invis.io/TB13E62NWP3D

Content:

Form with the following fields

  • Pixel ID [string] (required)
  • Access Token [string] (required)

3) Events to be implemented

  • Add to cart
    • Triggering logic:
      Trigger event once the addToCart API is calling (once clicking Add to cart) with a successful response (if an error occurred or not enough inventory - it would not be triggered)
  • Start placing an order
    • Triggering logic:
      Trigger event once any form with type checkout is loading on the page
  • Purchase
    • Triggering logic:
      Trigger event once form with payment is successfully submitted (event would be sent regardless of the payment result. The only blocking condition would be if a payment request would not be created successfully.
  • Lead
    • Triggering logic:
      Trigger event once any form without password field is sent
  • Completed registration
    • Triggering logic:
      Trigger event once any form with password field is sent

Google analytics events output via component and API

1) Event analytics retrieving logic

This logic is accessible only if GA4 analytics is set up in the admin panel.

Retrieve data using the following GA4 API:
https://developers.google.com/analytics/devguides/reporting/data/v1/rest/v1beta/properties/runReport

Request JSON example:

    {
        "dimensions": [
            {
                "name": "date"
            },
            {
                "name": "eventName"
            },
            {
                "name": "customEvent:coupon_code"
            },
            {
                "name": "customEvent:user"
            }
        ],
        "metrics": [
            {
                "name": "eventCount"
            }
        ],
        "dateRanges": [
            {
                "startDate": "2023-07-03",
                "endDate": "2023-07-05"
            }
        ],
        "dimensionFilter": {
            "andGroup": {
                "expressions": [
                    {
                        "filter": {
                            "stringFilter": {
                                "matchType": "EXACT",
                                "value": "coupon_code_clicked"
                            },
                            "fieldName": "eventName"
                        }
                    },
                    {
                        "filter": {
                            "stringFilter": {
                                "matchType": "EXACT",
                                "value": "My CUSTOm CODE"
                            },
                            "fieldName": "customEvent:coupon_code"
                        }
                    }
                ]
            }
        },
        "limit": "100",
        "orderBys": [
            {
                "dimension": {
                    "orderType": "ALPHANUMERIC",
                    "dimensionName": "date"
                },
                "desc": false
            }
        ],
        "keepEmptyRows": true
    }

2) Liquid component

Component pattern:

{% component type:"frontend_API", endpoint:"/api/frontend/ga4_run_report",  request: "[[request]]", layout:"", collectionVariable:"" %}

Params description:

  • request
  • layout
    • Default component logic should be applied here.
    • Success response JSON object should be attached to liquid this.response variable
    • Error response JSON object should be attached to liquid this.errorMessages param.
      Example: "errorMessages": []
    • Number of errors should be attached to liquid this.error param.
      Example: "error": 0
    • Default layout is empty
  • Response {{this.response}} object:
        {
            "dimensionHeaders": [
                {
                    "name": "date"
                },
                {
                    "name": "eventName"
                },
                {
                    "name": "customEvent:coupon_code"
                },
                {
                    "name": "customEvent:user"
                }
            ],
            "metricHeaders": [
                {
                    "name": "eventCount",
                    "type": "TYPE_INTEGER"
                }
            ],
            "rows": [
                {
                    "dimensionValues": [
                        {
                            "value": "20230705"
                        },
                        {
                            "value": "coupon_code_clicked"
                        },
                        {
                            "value": "My CUSTOm CODE"
                        },
                        {
                            "value": "33"
                        }
                    ],
                    "metricValues": [
                        {
                            "value": "4"
                        }
                    ]
                },
                {
                    "dimensionValues": [
                        {
                            "value": "20230705"
                        },
                        {
                            "value": "coupon_code_clicked"
                        },
                        {
                            "value": "My CUSTOm CODE"
                        },
                        {
                            "value": "22"
                        }
                    ],
                    "metricValues": [
                        {
                            "value": "3"
                        }
                    ]
                },
                {
                    "dimensionValues": [
                        {
                            "value": "20230705"
                        },
                        {
                            "value": "coupon_code_clicked"
                        },
                        {
                            "value": "My CUSTOm CODE"
                        },
                        {
                            "value": "11"
                        }
                    ],
                    "metricValues": [
                        {
                            "value": "1"
                        }
                    ]
                },
                {
                    "dimensionValues": [
                        {
                            "value": "20230704"
                        },
                        {
                            "value": "coupon_code_clicked"
                        },
                        {
                            "value": "My CUSTOm CODE"
                        },
                        {
                            "value": "22"
                        }
                    ],
                    "metricValues": [
                        {
                            "value": "4"
                        }
                    ]
                },
                {
                    "dimensionValues": [
                        {
                            "value": "20230704"
                        },
                        {
                            "value": "coupon_code_clicked"
                        },
                        {
                            "value": "My CUSTOm CODE"
                        },
                        {
                            "value": "11"
                        }
                    ],
                    "metricValues": [
                        {
                            "value": "3"
                        }
                    ]
                },
                {
                    "dimensionValues": [
                        {
                            "value": "20230704"
                        },
                        {
                            "value": "coupon_code_clicked"
                        },
                        {
                            "value": "My CUSTOm CODE"
                        },
                        {
                            "value": "(not set)"
                        }
                    ],
                    "metricValues": [
                        {
                            "value": "2"
                        }
                    ]
                },
                {
                    "dimensionValues": [
                        {
                            "value": "20230704"
                        },
                        {
                            "value": "coupon_code_clicked"
                        },
                        {
                            "value": "My CUSTOm CODE"
                        },
                        {
                            "value": "33"
                        }
                    ],
                    "metricValues": [
                        {
                            "value": "1"
                        }
                    ]
                }
            ],
            "totals": [
                {
                    "dimensionValues": [
                        {
                            "value": "RESERVED_TOTAL"
                        },
                        {
                            "value": "RESERVED_TOTAL"
                        },
                        {
                            "value": "RESERVED_TOTAL"
                        },
                        {
                            "value": "RESERVED_TOTAL"
                        }
                    ],
                    "metricValues": [
                        {
                            "value": "18"
                        }
                    ]
                }
            ],
            "rowCount": 7,
            "metadata": {
                "currencyCode": "USD",
                "timeZone": "America/Los_Angeles"
            },
            "kind": "analyticsData#runReport"
        }
    

3) API Endpoint via frontend API

Create a new frontend API endpoint

Endpoint: /api/frontend/ga4_run_report

Type: GET

Params: request value is URL encoded JSON string as per the following documentation:
https://developers.google.com/analytics/devguides/reporting/data/v1/rest/v1beta/properties/runReport#request-body

Example:

/api/frontend/ga4_run_report?request=%7B%22dimensions%22%3A%5B%7B%22name%22%3A%22date%22%7D%2C%7B%22name%22%3A%22eventName%22%7D%2C%7B%22name%22%3A%22customEvent%3Acoupon_code%22%7D%2C%7B%22name%22%3A%22customEvent%3Auser%22%7D%5D%2C%22metrics%22%3A%5B%7B%22name%22%3A%22eventCount%22%7D%5D%2C%22dateRanges%22%3A%5B%7B%22startDate%22%3A%222023-07-03%22%2C%22endDate%22%3A%222023-07-05%22%7D%5D%2C%22dimensionFilter%22%3A%7B%22andGroup%22%3A%7B%22expressions%22%3A%5B%7B%22filter%22%3A%7B%22stringFilter%22%3A%7B%22matchType%22%3A%22EXACT%22%2C%22value%22%3A%22coupon_code_clicked%22%7D%2C%22fieldName%22%3A%22eventName%22%7D%7D%2C%7B%22filter%22%3A%7B%22stringFilter%22%3A%7B%22matchType%22%3A%22EXACT%22%2C%22value%22%3A%22My%20CUSTOm%20CODE%22%7D%2C%22fieldName%22%3A%22customEvent%3Acoupon_code%22%7D%7D%5D%7D%7D%2C%22limit%22%3A%22100%22%2C%22orderBys%22%3A%5B%7B%22dimension%22%3A%7B%22orderType%22%3A%22ALPHANUMERIC%22%2C%22dimensionName%22%3A%22date%22%7D%2C%22desc%22%3Atrue%7D%5D%2C%22keepEmptyRows%22%3Atrue%7D

4) API Endpoint restrictions

Add API Endpoint restrictions:

see 2) “API Endpoint restrictions logic” (ie: Disallow processing API if the current logged-in user is mismatched with the restrictions)

5) Default include file for chart

Create default chart inside include file: /cms-assets/includes/ga4-report-chart.inc

Add ability to redraw chart on selecting different:

  • Start Date
  • End Date

Use API calls in order to retrieve new values

6) Add component to toolbox

Add to toolbox: “Frontend API” > “GA4 Report Chart”

Params:

  • startDate (default: {{"now" | date_add: -1, "month" | date: "%Y-%m-%d" }})
  • endDate (default: {{"now" | date: "%Y-%m-%d" }})
  • eventName (default: page_view)
  • requestJSON (default: see "Content" from section (5))
    • if provided - ignore all params above.

Output Value

{% include "/cms-assets/includes/ga4-report-chart.inc", startDate: "", endDate: "", eventName: "", requestJSON: "" %}

Secure Zone Subscribers analytics

1) Liquid component

Component pattern:

{% component type:"frontend_API", endpoint:"/api/frontend/secure_zone_subscribers_analytics", request:"[[request]]",  layout:"", collectionVariable:"" %}

Request expression pattern:

    {
        "startDate": "[[startDate]]",
        "endDate": "[[endDate]]",
        "filterExpression": [[filterJSONExpression]],
        "sortExpression": [[sortJSONExpression]],
        "groupType": "[[groupType]]"
    }

Description of the expression params:

[[startDate]]

  • allowed format: yyyy-mm-dd (if format not matched - use default: NOW date)

[[endDate]]

  • allowed format: yyyy-mm-dd (if format not matched - use default: startDate + one day)

[[filterJSONExpression]]

  • Expression pattern:
    [
        {
            "secureZones": [
                [[secureZoneId1]],
                [[secureZoneId2]],
                [[secureZoneIdN]]
            ]
        }
    ]
    
  • If supplied string could not be parsed as JSON - use default expression of empty array:
    [
        {
            "secureZones": []
        }
    ]
    

    Logic:
    IF secureZones is an empty array, retrieve stats for all secure zones.
    ELSE retrieve stats only for selected secure zones.

[[sortJSONExpression]]

  • Expression pattern (default):
    [
        {
            "sortBy": "date",
            "sortOrder": "ASC"
        }
    ]
    

    Allowed `sortBy` values: date
    If supplied string could not be parsed as JSON - use default expression

[[groupType]]

  • Possible values
    • Day (default)
    • Week
    • Month
    • Year

    If param is not specified - use default value

Full example of the request expresion:

{
    "startDate": "2023-10-01",
    "endDate": "2023-11-10",
    "filterExpression": [
        {
            "secureZones": [
                111,
                222,
                333
            ]
        }
    ],
    "sortExpression": [
        {
            "sortBy": "date",
            "sortOrder": "ASC"
        }
    ],
    "groupType": "Day"
}

Layout:

  • Default component logic should be applied here.
  • Response JSON object should be attached to liquid this.response variable
  • Default layout is empty

Response {{this.response}} object example:

    {
        "rows": [
            {
                "dimensionValues": [
                    {
                        "value": "Date"
                    },
                    {
                        "value": "Total"
                    },
                    {
                        "value": "secure zone 1"
                    },
                    {
                        "value": "secure zone 2"
                    },
                    {
                        "value": "secure zone 3"
                    }
                ],
                "metricValues": [
                    {
                        "value": "20230705"
                    },
                    {
                        "value": 39 //total number of subscribers to all selected secure zones
                    },
                    {
                        "value": 4 //number of subscribers to secure zone 1
                    },
                    {
                        "value": 2 //number of subscribers to secure zone 2
                    },
                    {
                        "value": 33 //number of subscribers to secure zone 3
                    }
                ]
            }
        ],
        "rowCount": 1
    }

2) API Endpoint via frontend API

Create a new frontend API endpoint

Endpoint: /api/frontend/secure_zone_subscribers_analytics

Type: GET

Params: `request` (URL encoded JSON string like in request for liquid object):
{"startDate":"2023-10-01","endDate":"2023-11-10","filterExpression":[{"secureZones":[111,222,333]}],"sortExpression":[{"sortBy":"date","sortOrder":"ASC"}],"groupType":"Day"}

Example:

/frontend_api/secure_zone_subscribers_analytics?request=%7B%22startDate%22%3A%222023-10-01%22%2C%22endDate%22%3A%222023-11-10%22%2C%22filterExpression%22%3A%5B%7B%22secureZones%22%3A%5B111%2C222%2C333%5D%7D%5D%2C%22sortExpression%22%3A%5B%7B%22sortBy%22%3A%22date%22%2C%22sortOrder%22%3A%22DESC%22%7D%5D%2C%22groupType%22%3A%22Day%22%7D

3) API Endpoint restrictions

Add API Endpoint restrictions:

see 2) “API Endpoint restrictions logic” (ie: Disallow processing API if the current logged-in user is mismatched with the restrictions)

4) Default include file for chart

Create default chart inside include file:
/cms-assets/includes/secure-zone-analytics-chart.inc

Add ability to redraw chart on selecting different:

  • Group Type
    • Day
    • Week
    • Month
    • Year
  • Start Date
  • End Date

Use API calls in order to retrieve new values

Content:

{% capture requestJSON %}
{
    "startDate": "{{startDate}}",
    "endDate": "{{endDate}}",
    "filterExpression": [
        {
            "secureZones": [{{secureZonesList}}]
        }
    ],
    "sortExpression": [
        {
            "sortBy": "date",
            "sortOrder": "ASC"
        }
    ],
    "groupType": "{{groupType | default : "Day"}}"
}
{% endcapture %}
{% component type:"frontend_API", endpoint:"/api/frontend/secure_zone_subscribers_analytics",  request: "{{requestJSON}}", layout:"", collectionVariable:"frontendAPIResponse" %}

Use frontendAPIResponse for the first draw and pass it to JS in order to determine request structure for the change startDate, endDate and groupType.

5) Add component to toolbox

Add to toolbox: ‘Frontend API’ > ‘Secure Zones Analytics Chart’

Params:

  • startDate (default: {{"now" | date_add: -1, "month" | date: "%Y-%m-%d" }})
  • endDate (default: {{"now" | date: "%Y-%m-%d" }})
  • secureZonesList (default: "")
    • if passed, should be a CSV string of secure zones ids (example "111,222,333")
  • groupType (default: "")
  • requestJSON (default: see "Content" from section (4))
    • if provided - ignore all params above.

Output Value

{% include "/cms-assets/includes/secure-zone-analytics-chart.inc", startDate: "", endDate: "", secureZonesList: "", groupType: "", requestJSON: "" %}

Module Item frontend API forms extending

1) Add permissions to Module -> `Site User permission`

Add following permission to the settings:

  • Allow Save Draft
  • Allow Publish Draft

Add workflow selector for each new permission

2) Rework Module -> `Site User permission` and Module -> `Autoresponder` tabs

  • Site User permission
    • Add API Endpoint restrictions (ability to set API Endpoint restrictions for each permission of the particular module):
      • see 2) “API Endpoint restrictions logic” (ie: Disallow processing API if the current logged-in user is mismatched with the restrictions)
  • Autoresponder updates:
    • Provide ability to configure all autoresponer settings for each action from permission list instead of "one single autoresponder for all actions":
      • Create module item
      • Update module item
      • Delete module item
      • Update draft module item
      • Publish draft module item
    • Migrate autoresponder settings from "one single autoresponder for all actions" to the following permission-specific autoresponders:
      • Create module item
      • Update module item
      • Delete module item
    • Set empty autoresponder settings for the new permission-specific autoresponders:
      • Update draft module item
      • Publish draft module item
    • Extend autoresponder settings
      • Setting: Receiver (Select element)
        • Form sender (default)
        • Item owner
        • Sender and owner
      • Logic:
        Receiver setting will determine what email to use as email receiver - current logged in user or actual item owner.
        Notes: on create item action there will be no difference between both options because item will be created by curren logged in user

Design: https://invis.io/NE13B20N72DB

3) Add Public API for Save Draft and Publish Draft

Add 2 new public APIs (similar to edit module item from frontend froms https://prnt.sc/OYeHVehTlJJI):

  • /public/api/module-items/update-draft
  • /public/api/module-items/publish-draft

Actions:

  • Send workflow if selected in Module -> Site User permission
  • Send API specific autoresponder if enabled and configured for certain API in Module -> Site User permission
  • Disallow to perform action if Module -> Site User permission ->  API Endpoint restrictions disallows current user to perform it

4) Update the toolbox with the new forms

Add forms to the toolbox (https://prnt.sc/pCCWR5PwOdny)

  • Update Item's Draft Form
  • Publish Item's Draft Form

5) Add param to the `module` and `module_of_member` components to receive draft versions of the items

Add param:

  • getDraft
    • true
    • false (default)

Logic:
if true; returns draft version of the item data insted of the public one.

6) Add URL param for the draft version of the item displaying

If url contains following get param - return draft version of the item taken by the URL instead of the public one:

  • ?DraftPreview=true

Frontend API access restrictions

1) Add API Endpoint restrictions setup page

Add new page: ‘Settings’ -> ‘Frontend API restrictions’

Design: https://invis.io/TY13B20D96NJ

2) API Endpoint restrictions logic

Restriction settings:

  • Enable/disable endpoint
  • API allowed to the following type of users:
    • Logged in users (default)
    • User from the following secure zones:
      • if this option selected - show list of the secure zones.
        Only users with access to ANY of the selected secure zones would be allowed to use API.
    • Admin Users
  • Ownership restriction (where API relates to entities having ownership):
    • Only Owner allowed (default) (only owner can perform an action or any user that belongs to the type determined above)
    • Anyone allowed

Restrictions can be applied to the following frontend APIs:

  • Create Module Item
  • Update Module Item
  • Delete Module Item
  • Update Draft Module Item
  • Publish Draft Module Item
  • Google analytics report
  • Secure zone subscribers analytics

3) Admin restrictions

Add to restrictions

  • Frontend API restrictions
    • Can View
    • Can Edit

4) Plan restriction

Min plan available: Essential

Category in module item view improvement

Example category structure

The module has selected 1-st level  category named AD-1 parent category as the parent category

Improvements:

1) Search by values

Add ability to search by values

2) Increase the number of shown items

Increase the number of show items to 12 https://prnt.sc/gYrGU-kV1IGl (currently shown 6 https://prnt.sc/glmHDzSt0dG8)

3) Category level output improvement

3.1) Feature flag

Add feature flag

Name: "Improved level displaying on category dropdown"

Description:
Removes redundant level 4-dashes ("----") on output if parent category is not root (on component category and add/edit module item forms)

3.2) On module item add/edit form

Show dashes based on displayed level of categories instead of actual

Current: https://prnt.sc/glmHDzSt0dG8

Improved: https://prnt.sc/FqEKrW2X3dum

Add change under feature flag

3.3) On component category

Show dashes based on displayed level of categories instead of actual level:

{% component type:"categories",  parentCategory:"[[parentCategoryId]]" %}

Subscriptions list to contact liquid object

1) Extend CRM contact liquid object with the recurring subscriptions list

Add property with a list of recurring subscriptions to the {{request.currentmember}} liquid object and {% component type: "CRMContacts" %}

Property Name: recurringsubscriptions

Value (list of recurring subscriptions objects):

[
    {
        "Code": "I-XXXXXXXXX",
        "Status": "Active",
        "MemberId": 1000,
        "RecurringProducts": [
            {
                "Id": 1002,
                "Name": "Some Membership",
                "EntityType": "ModuleItem"
            }
        ]
    }
]

2) Add a checkbox includeSecureZonesInfo to liquid component List of CRM Contacts in toolbox

If includeRecurringSubscriptions is true add recurringsubscriptions to member object.

If includeRecurringSubscriptions is false add emptylist recurringsubscriptions to member object

If param is not set to the component - apply false by default

WYSISYG: custom widgets

1) Add a page to create/update/delete and see a list of custom widgets for WYSIWYG

Add a new tab to ‘Settings’ -> ‘Misc’

Tab Name: WYSIWYG: CUSTOM WIDGETS

Content:
List of custom widgets with ability to create, update and delete them (https://prnt.sc/325Q0XSoM0yn)

2) Add the ability to insert a custom widget via WYSIWYG

Add button to the WYSIWYG that will allow admin user to select widget and add it to the content (https://prnt.sc/UrvFuHc3Gdhx)

Add nonce attribute support for CSP

1) Add nonce hash variable to the liquid context

Add liquid Property "cspNonceHash" which will contain a unique generated hash for the unique HTTP request.

In order to allow scripts to be loaded on the site add nonce attribute to each of them

  • <script nonce="{{cspNonceHash}}">alert(9);</script>
  • <script nonce="{{cspNonceHash}}" src="/js/my-main.js">alert(9);</script>

2) Add dynamic 'nonce' support in header settings

In order to tell the system to generate random hash on each request to the site for the nonce header param - add following string to the header field

  • 'nonce-cspNonceHash'

Once page would be rendered - header would output nonce param with random hash and the same hash would be available via liquid {{cspNonceHash}} variable.

Example:

  • HTTP Header Settings for: Content-Security-Policy:
  • Field: script-src
  • Value: 'self' 'nonce-cspNonceHash'
  • Page content:
                            <html>
    <head>
     <script nonce="{{cspNonceHash}}" src="/js/my-main.js">alert(9);</script>
       </head>
    <body>
     <script nonce="{{cspNonceHash}}">alert(9);</script>
    </body>
    </html>

Would be rendered:

  • HTTP Header Settings for: Content-Security-Policy:
  • Field: script-src
  • Value: 'self' 'nonce-9a9946d409f83d6e3e2ce883ef16a08f '
  • Page content:
                            <html>
    <head>
     <script nonce="9a9946d409f83d6e3e2ce883ef16a08f " src="/js/my-main.js">alert(9);</script>
       </head>
    <body>
     <script nonce="9a9946d409f83d6e3e2ce883ef16a08f ">alert(9);</script>
       </body>
    </html>

Reference link:
https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/nonce

Site search keywords case insensitive search

Improve site search to find items by keywords in case insensitive manner

Example:

  • Module item:
    • Name: “Test”
    • Keywords: “SomeKeyword,Someword”
    • Description: “Some text”
  • Expected behavior
    • when searching via site search using the search string "somekeyword"
    • should find module item with the name “Test”
  • Current behavior
    • when searching via site search using the search string "somekeyword"
    • module item with the name "Test" would not be found due to mismatched letter case in “somekeyword”

Unique, hash and random value liquid filters

1) Add a "Unique" liquid filter

Add new string filter:

Name: unique_value

Syntax: {{ "anystring" | unique_value : "[[format]]"}}

Params [[format]]:

  • N or n
  • D or d
  • B or b
  • P or p
  • X or x

Output format:

  • Liquid String

Examples with output:

{{ "" | unique_value : "n"}}
234fa26ee4c14ea8b3b916d15982d410


{{ "" | unique_value : "d"}}
234fa26e-e4c1-4ea8-b3b9-16d15982d410


{{ "" | unique_value : "b"}}
{234fa26e-e4c1-4ea8-b3b9-16d15982d410}


{{ "" | unique_value : "p"}}
(234fa26e-e4c1-4ea8-b3b9-16d15982d410)


{{ "" | unique_value : "x"}}
{0x234fa26e,0xe4c1,0x4ea8,{0xb3,0xb9,0x16,0xd1,0x59,0x82,0xd4,0x10}}

2) Add a "Random" liquid filter

Add new number filter:

Name: random

Syntax: {{ "anystring" | random: "[[min_value]]","[[max_value]]"}}

Params:

  • [[min_value]] (number)
  • [[max_value]] (number)

Output format:

  • Liquid Number

Example with output:

{{ "" | random: "0","100"}}
46

{{ "" | random: "0","100"}}
18

3) Add "Hash" liquid filter

Add new string filter:

Name: hash

Syntax: {{ "anystring" | hash : "[[hash_algorithm]]"}}

Params:

  • [[hash_algorithm]]
    Values:
    • md5
    • hmacmd5
    • sha1
    • hmacsha1
    • sha256
    • hmacsha256
    • sha512
    • hmacsha512
    • base64  

Output format:

  • Liquid String

Examples with output:

{{ "test1" | hash : "md5"}}
5a105e8b9d40e1329780d62ea2265d8a

{{ "test1" | hash : "hmacmd5"}}
1F5DDC06F9A25B02F58EF47E0A223288

{{ "test1" | hash : "sha1"}}
B444AC06613FC8D63795BE9AD0BEAF55011936AC

{{ "test1" | hash : "hmacsha1"}}
7C9CDF43AD36F6A35053CD9676733D40CC5DDCFF

{{ "test1" | hash : "sha256"}}
1B4F0E9851971998E732078544C96B36C3D01CEDF7CAA332359D6F1D83567014

{{ "test1" | hash : "hmacsha256"}}
DE7762D598CB0B6A8B354BF11C90A313E2888545CFC1B84CE24A191DD8E6D631

{{ "test1" | hash : "sha512"}}
B16ED7D24B3ECBD4164DCDAD374E08C0AB7518AA07F9D3683F34C2B3C67A15830268CB4A56C1FF6F54C8E54A795F5B87C08668B51F82D0093F7BAEE7D2981181

{{ "test1" | hash : "hmacsha512"}}
C2E390DEE58F2DFF074A38E60E40353795DD7EF0514A57C9DE366E179DEF57F5C4133A2BE1E83AA625D2ACB4C47EFC1B7F92214016E71A54D2B2587FBB110382

{{ "test1" | hash : "base64"}}
dGVzdDE=​

Show more less
New Feature

Frontend API access restrictions

Provide the ability to restrict access to the following frontend API's:
- Create module item
- Update module item
- Delete module item
- Update draft module item
- Publish draft module item
- Google analytics report
- Secure zone subscribers analytics

Restriction criteria include:
1) User type restrictions setting
- Logged-in users
- User from one...
New Feature

Google Analytics events output via component and API

Ability to retrieve Google Analytics Events via liquid component and frontend API using reporting GA4 API: Method: properties.runReport
New Feature

Module Item frontend API forms extending

Provide ability to perform "save draft" and "publish draft" module item functionality via frontend forms similar to Create/Update module item forms.
Add getDraft parameter to the {% component type:"module" %}
Provide ability to configure unique autoresponders for each module item form:
- Create module item
- Update module item
- Delete module item
- Update draft module item
- Publish...
New Feature

Secure Zone Subscribers Analytics

Add secure zone subscribers analytics via liquid component and API (shows number of subscribers to the provided secure zones per each Day/Week/Month/Year in the provided date range).
New Feature

Unique, hash and random value liquid filters

Add "Unique", "Hash" and "Random" liquid filters
"Unique" liquid filter should return uniquid guid value
"Random" liquid filter should return random number between min and max value
"Hash" liquid filter should return a hash of the string the filter is applied to.
  • Liquid
New Feature

WYSIWYG: custom widgets

Provide the ability to create/update and delete custom HTML widgets for WYSIWYG and the ability to insert them using WYSIWYG.
Improvement

Added "nonce" attribute support for CSP

Extend "HTTP Header Settings" -> Content Security Policy header functionality to natively support "nonce" param.
Improvement

Category in the module item view improvement

Remove redundant level 4-dashes ("----") in the output if parent category is not root:
- in the {% component type:"categories", parentCategory:"[[parentCategoryId]]" %}
- in the add/edit module item forms of admin UI
Improvement

Extended request.currentmember liquid object

Add a list of payment subscriptions to the request.currentmember liquid object.
It allows to determine if the current member has active recurring subscriptions and what products or secure zones they are assigned to.
Improvement

Site search case insensitivity improvement

Improve site search to use case insensitive search by module item keywords