Skip to content

Commit

Permalink
✨[amp-analytics] New macro $CALC to perform basic arithmetic on analy…
Browse files Browse the repository at this point in the history
…tics variables and macros. (#33383)

* New  macro for performing basic arithmetic on other macros and variables

* fixed suggestions from prettify

* added testcase to cover default flow

* Added a new flag to round the results to integer

This flag is helpful as some vendors like google analytics expects event
value to be an integer.

* assert when rightOperand is 0 while dividing

* calc operations are lowercase to honor macro coding convention
  • Loading branch information
raja-anbazhagan committed Mar 22, 2021
1 parent e90491f commit 0e11de9
Show file tree
Hide file tree
Showing 3 changed files with 98 additions and 14 deletions.
34 changes: 34 additions & 0 deletions extensions/amp-analytics/0.1/test/test-variables.js
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,40 @@ describes.fakeWin('amp-analytics.VariableService', {amp: true}, (env) => {
return check('$BASE64(Hello World!)', 'SGVsbG8gV29ybGQh');
});

describe('$CALC', () => {
it('calc addition works', () => check('$CALC(1, 2, add)', '3'));

it('calc addition works with rounding flag', () =>
check('$CALC(1, 2, add, true)', '3'));

it('calc subtraction works', () =>
check('$CALC(1, 2, subtract, true)', '-1'));

it('calc multiplication works', () =>
check('$CALC(1, 2, multiply, true)', '2'));

it('calc division works', () =>
check('$CALC(1, 2, divide, false)', '0.5'));

it('calc division should round 2/3 to 1', () =>
check('$CALC(2, 3, divide, true)', '1'));

it('calc division should round 1/3 to 0', () =>
check('$CALC(1, 3, divide, true)', '0'));

it('calc division should round 1/2 to 1', () =>
check('$CALC(1, 2, divide, true)', '1'));

it('calc with unknown operation defaults to zero', () =>
check('$CALC(1, 2, somethingelse, true)', '0'));

it('calc with nested macro works', () =>
check('$CALC($SUBSTR(123456, 2, 5), 10, multiply, false)', '34560'));

it('calc should replace CUMULATIVE_LAYOUT_SHIFT with 1', () =>
check('$CALC(CUMULATIVE_LAYOUT_SHIFT, 10, multiply, true)', '10'));
});

it('if works with true', () =>
check('$IF(true, truthy, falsey)', 'truthy'));

Expand Down
36 changes: 36 additions & 0 deletions extensions/amp-analytics/0.1/variables.js
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,41 @@ function matchMacro(string, matchPattern, opt_matchingGroupIndexStr) {
return matches && matches[index] ? matches[index] : '';
}

/**
* This macro function allows arithmetic operations over other analytics variables.
*
* @param {string} leftOperand
* @param {string} rightOperand
* @param {string} operation
* @param {string} round If this flag is truthy the result will be rounded
* @return {number}
*/
function calcMacro(leftOperand, rightOperand, operation, round) {
const left = Number(leftOperand);
const right = Number(rightOperand);
userAssert(!isNaN(left), 'CALC macro - left operand must be a number');
userAssert(!isNaN(right), 'CALC macro - right operand must be a number');
let result = 0;
switch (operation) {
case 'add':
result = left + right;
break;
case 'subtract':
result = left - right;
break;
case 'multiply':
result = left * right;
break;
case 'divide':
userAssert(right, 'CALC macro - cannot divide by 0');
result = left / right;
break;
default:
user().error(TAG, 'CALC macro - Invalid operation');
}
return stringToBool(round) ? Math.round(result) : result;
}

/**
* If given an experiment name returns the branch id if a branch is selected.
* If no branch name given, it returns a comma separated list of active branch
Expand Down Expand Up @@ -230,6 +265,7 @@ export class VariableService {
);
this.register_('$REPLACE', replaceMacro);
this.register_('$MATCH', matchMacro);
this.register_('$CALC', calcMacro);
this.register_(
'$EQUALS',
(firstValue, secValue) => firstValue === secValue
Expand Down
42 changes: 28 additions & 14 deletions spec/amp-var-substitutions.md
Original file line number Diff line number Diff line change
Expand Up @@ -277,20 +277,21 @@ The tables below list the available URL variables grouped by type of usage. Furt

### Analytics Advanced Variable Syntax

| Variable Name | Platform Variable | amp-analytics Variable |
| --------------------------- | ----------------- | ---------------------- |
| [Default](#default) | N/A | `$DEFAULT` |
| [SubStr](#string-substr) | N/A | `$SUBSTR` |
| [Trim](#trim) | N/A | `$TRIM` |
| [ToLowerCase](#tolowercase) | N/A | `$TOLOWERCASE` |
| [ToUpperCase](#touppercase) | N/A | `$TOUPPERCASE` |
| [Not](#not) | N/A | `$NOT` |
| [Base64](#base64) | N/A | `$BASE64` |
| [Hash](#hash) | N/A | `$HASH` |
| [If](#if) | N/A | `$IF` |
| [Replace](#replace) | N/A | `$REPLACE` |
| [Match](#match) | N/A | `$MATCH` |
| [Equals](#equals) | N/A | `$EQUALS` |
| Variable Name | Platform Variable | amp-analytics Variable |
| ---------------------------- | ----------------- | ---------------------- |
| [Default](#default) | N/A | `$DEFAULT` |
| [SubStr](#string-substr) | N/A | `$SUBSTR` |
| [Trim](#trim) | N/A | `$TRIM` |
| [ToLowerCase](#tolowercase) | N/A | `$TOLOWERCASE` |
| [ToUpperCase](#touppercase) | N/A | `$TOUPPERCASE` |
| [Not](#not) | N/A | `$NOT` |
| [Base64](#base64) | N/A | `$BASE64` |
| [Hash](#hash) | N/A | `$HASH` |
| [If](#if) | N/A | `$IF` |
| [Replace](#replace) | N/A | `$REPLACE` |
| [Match](#match) | N/A | `$MATCH` |
| [Equals](#equals) | N/A | `$EQUALS` |
| [Simple Calculations](#calc) | N/A | `$CALC` |

### Miscellaneous

Expand Down Expand Up @@ -1374,3 +1375,16 @@ Find the specified (or first) matched pattern.
##### Equals

- Example: `$EQUALS(${val}, value)` resolves to `'true'` or `'false'`

##### Simple Calculations

This macro allows you to perform basic arithmetics like addition, subtraction, multiplication and division.

Parameters:

- **leftOperand** : A variable or a literal that resolves to a number or, a number string.
- **rightOperand** : A variable or a literal that resolves to a number or, a number string.
- **operation** : A literal. One of `add`, `subtract`, `multiply`, `divide`.
- **round** : An optional flag. If truthy, the result will be rounded.

Example: `$CALC(${cumulativeLayoutShift}, 1000, multiply, true)`

0 comments on commit 0e11de9

Please sign in to comment.