@@ -4,58 +4,84 @@ import OptimizeContext from "./OptimizeContext";
44
55class Experiment extends React . Component {
66 static defaultProps = {
7- loader : null
7+ loader : null ,
8+ timeout : 3000
89 } ;
910
1011 static propTypes = {
1112 id : PropTypes . string . isRequired ,
1213 loader : PropTypes . node ,
14+ timeout : PropTypes . number ,
1315 children : PropTypes . node
1416 } ;
1517
1618 state = {
1719 variant : null
1820 } ;
1921
22+ updateVariantTimeout = null ;
23+
2024 updateVariant = value => {
25+ clearTimeout ( this . updateVariantTimeout ) ;
2126 // if experiment not active, render original
22- this . setState ( {
23- variant : value === undefined || value === null ? "0" : value
24- } ) ;
27+ const newVariant = value === undefined || value === null ? "0" : value ;
28+ if ( newVariant !== this . state . variant ) {
29+ this . setState ( {
30+ variant : newVariant
31+ } ) ;
32+ }
2533 } ;
2634
27- delayedInitialization = ( ) => {
35+ updateVariantFromGlobalState = ( ) => {
2836 const value =
29- window . google_optimize && window . google_optimize . get ( this . props . id ) ;
37+ typeof window !== "undefined" && window . google_optimize
38+ ? window . google_optimize . get ( this . props . id )
39+ : null ;
3040 this . updateVariant ( value ) ;
3141 } ;
3242
43+ setupOptimizeCallback = ( ) => {
44+ this . updateVariantTimeout = setTimeout (
45+ this . updateVariantFromGlobalState ,
46+ this . props . timeout
47+ ) ;
48+ const oldHideEnd = window . dataLayer . hide . end ;
49+ window . dataLayer . hide . end = ( ) => {
50+ this . updateVariantFromGlobalState ( ) ;
51+ oldHideEnd && oldHideEnd ( ) ;
52+ } ;
53+
54+ window . gtag &&
55+ window . gtag ( "event" , "optimize.callback" , {
56+ name : this . props . id ,
57+ callback : this . updateVariant
58+ } ) ;
59+ } ;
60+
3361 componentDidMount ( ) {
3462 if ( ! this . props . id ) {
3563 throw new Error ( "Please specify the experiment id" ) ;
3664 }
3765
3866 // Delayed init
39- const hideEnd =
40- window . dataLayer && window . dataLayer . hide && window . dataLayer . hide . end ;
41- if ( hideEnd ) {
42- window . dataLayer . hide . end = ( ) => {
43- this . delayedInitialization ( ) ;
44- hideEnd ( ) ;
45- } ;
67+ if ( typeof window !== "undefined" && ! window . google_optimize ) {
68+ if ( ! window . dataLayer ) {
69+ window . dataLayer = [ ] ;
70+ }
71+ if ( ! window . dataLayer . hide ) {
72+ window . dataLayer . hide = { start : Date . now ( ) } ;
73+ }
74+
75+ this . setupOptimizeCallback ( ) ;
4676 } else {
47- this . delayedInitialization ( ) ;
77+ // Google Optimize already loaded, or we're doing server-side rendering
78+ this . updateVariantFromGlobalState ( ) ;
4879 }
49-
50- window . gtag &&
51- window . gtag ( "event" , "optimize.callback" , {
52- name : this . props . id ,
53- callback : this . updateVariant
54- } ) ;
5580 }
5681
5782 componentWillUnmount ( ) {
58- window . gtag &&
83+ typeof window !== "undefined" &&
84+ window . gtag &&
5985 window . gtag ( "event" , "optimize.callback" , {
6086 name : this . props . id ,
6187 callback : this . updateVariant ,
0 commit comments