diff --git a/apps/common/create-api-client.js b/apps/common/create-api-client.js
index 48e7a77..0347ca3 100644
--- a/apps/common/create-api-client.js
+++ b/apps/common/create-api-client.js
@@ -1,5 +1,6 @@
 import axios from 'axios';
 import config from 'config';
+import {get} from 'lodash';
 
 axios.defaults.baseURL = config.axiosBaseUrl;
 axios.defaults.responseType = config.axiosResponseType;
@@ -8,12 +9,22 @@ axios.defaults.headers = {
 };
 
 const errHandle = (error) => {
+  let res = error.response;
+
   console.log(error);
+
+  if (+res.status === 510) {
+    if (get(res, 'data.data.refer')) {
+      return window.location.href = get(res, 'data.data.refer');
+    }
+  }
+
   return Promise.reject({
     code: 500,
     message: '服务器开小差了~'
   });
 };
+
 const request = (options, store) => {
   return axios(options).then((res) => {
     if (res.data.code === 401) {
diff --git a/apps/components/comments/comment-item.vue b/apps/components/comments/comment-item.vue
index 5331992..1d3c21c 100644
--- a/apps/components/comments/comment-item.vue
+++ b/apps/components/comments/comment-item.vue
@@ -17,6 +17,8 @@
 			<CommentPlaceholder
         class="comment-cont"
         :dest-id="parentComment.id"
+        :pos-id="posId"
+        :article-id="articleId"
         :add-type="1"
         :user="parentComment.userName"
         :column-type="columnType"
@@ -65,7 +67,9 @@ export default {
     columnType: {
       type: Number,
       default: 1001
-    }
+    },
+    posId: Number,
+    articleId: Number
   },
   data() {
     return {
diff --git a/apps/components/comments/comment-list.vue b/apps/components/comments/comment-list.vue
index 9773c7f..b9c555b 100644
--- a/apps/components/comments/comment-list.vue
+++ b/apps/components/comments/comment-list.vue
@@ -9,6 +9,8 @@
             :parent-comment="comment.parentComment"
             :children-comments="comment.childrenComments"
             :column-type="columnType"
+            :pos-id="posId"
+            :article-id="articleId"
             @on-reply="onReply">
           </CommentItem>
         </Scroll>
@@ -18,6 +20,8 @@
       <CommentPlaceholder
         class="comment-input"
         :dest-id="destId"
+        :pos-id="posId"
+        :article-id="articleId"
         :add-type="0"
         :column-type="columnType"
         @on-comment="onComment">
@@ -41,7 +45,9 @@ export default {
     columnType: {
       type: Number,
       default: 1001
-    }
+    },
+    posId: Number,
+    articleId: Number
   },
   data() {
     return {
diff --git a/apps/components/comments/comment-placeholder.js b/apps/components/comments/comment-placeholder.js
index 974e648..7197188 100644
--- a/apps/components/comments/comment-placeholder.js
+++ b/apps/components/comments/comment-placeholder.js
@@ -1,5 +1,6 @@
 import {createNamespacedHelpers} from 'vuex';
 const {mapActions} = createNamespacedHelpers('comment');
+import YAS from 'utils/yas-constants';
 const {mapActions: articleMapActions} = createNamespacedHelpers('article');
 
 export default {
@@ -16,7 +17,9 @@ export default {
       type: String,
       default: ''
     },
-    share: Boolean
+    share: Boolean,
+    posId: Number,
+    articleId: Number
   },
   data() {
     return {
@@ -80,6 +83,8 @@ export default {
           addType: this.addType,
           columnType: this.columnType
         });
+
+        this.reportComment(this.destId);
       } else {
         this.$createToast({
           txt: result.message || '服务器开小差了',
@@ -87,6 +92,18 @@ export default {
           time: 1000
         }).show();
       }
+    },
+    reportComment(comId) {
+      this.$store.dispatch('reportYas', {
+        params: {
+          appop: YAS.eventName.comment,
+          param: {
+            POS_ID: this.posId,
+            ARTICLE_ID: this.articleId,
+            COM_ID: this.addType === 1 ? comId : void 0
+          }
+        }
+      });
     }
   },
   render(h) {
diff --git a/apps/components/comments/comment.vue b/apps/components/comments/comment.vue
index 6237ce3..a041e2b 100644
--- a/apps/components/comments/comment.vue
+++ b/apps/components/comments/comment.vue
@@ -6,7 +6,7 @@
         <i class="iconfont icon-close icon" @touchend.prevent="onClose"></i>
       </template>
     </LayoutHeader>
-    <CommentList ref="commentList" :dest-id="destId" :column-type="1001" @on-page-change="onPageChange" @on-comment="onComment" @on-page-ready="onPageReady"></CommentList>
+    <CommentList ref="commentList" :dest-id="destId" :pos-id="posId" :article-id="articleId" :column-type="1001" @on-page-change="onPageChange" @on-comment="onComment" @on-page-ready="onPageReady"></CommentList>
   </Layout>
 </template>
 
@@ -20,7 +20,9 @@ export default {
     popup: {
       type: Boolean,
       default: false
-    }
+    },
+    posId: Number,
+    articleId: Number
   },
   data() {
     return {
diff --git a/apps/components/products/product-group-item.vue b/apps/components/products/product-group-item.vue
index 61a72e8..0fa25c1 100644
--- a/apps/components/products/product-group-item.vue
+++ b/apps/components/products/product-group-item.vue
@@ -20,6 +20,7 @@
 
 <script>
 import {createNamespacedHelpers} from 'vuex';
+import YAS from 'utils/yas-constants';
 const {mapActions} = createNamespacedHelpers('product');
 
 export default {
@@ -29,7 +30,10 @@ export default {
     lazy: Boolean,
     product: Object,
     share: Boolean,
-    thumb: Boolean
+    thumb: Boolean,
+    posId: Number,
+    articleId: [String, Number],
+    index: Number
   },
   data() {
     return {
@@ -78,6 +82,7 @@ export default {
 
       if (result.code === 200) {
         if (favorite) {
+          this.reportFavProduct(this.product.productSkn, this.product.productType);
           this.prompt = this.$grassPrompt({
             img: this.product.productImage,
             title: '收藏成功',
@@ -118,11 +123,41 @@ export default {
       if (!skn) {
         return;
       }
+
       if (this.product.productType === 1) {
         this.$yoho.goProductDetail(skn);
       } else if (this.product.productType === 2) {
         this.$yoho.goUfoProductDetail(skn);
       }
+
+      this.reportProduct(skn, this.product.productType);
+    },
+    reportProduct(skn, type) {
+      this.$store.dispatch('reportYas', {
+        params: {
+          appop: YAS.eventName.productClick,
+          param: {
+            POS_ID: this.posId,
+            ARTICLE_ID: this.articleId,
+            PRD_SKN: skn,
+            PRD_TYPE: type
+          }
+        }
+      });
+    },
+    reportFavProduct(skn, type) {
+      this.$store.dispatch('reportYas', {
+        params: {
+          appop: YAS.eventName.productFav,
+          param: {
+            POS_ID: this.posId,
+            ARTICLE_ID: this.articleId,
+            PRD_SKN: skn,
+            PRD_TYPE: type,
+            I_INDEX: this.index
+          }
+        }
+      });
     }
   }
 };
diff --git a/apps/components/products/product-group.vue b/apps/components/products/product-group.vue
index d4ee0a7..a6afbdf 100644
--- a/apps/components/products/product-group.vue
+++ b/apps/components/products/product-group.vue
@@ -6,8 +6,12 @@
       :thumb="thumb"
       :single="single"
       :product="product"
+      :article-id="articleId"
+      :pos-id="posId"
       :lazy="lazy"
-      :key="inx"></ProductGroupItem>
+      :index="index"
+      :key="inx">
+    </ProductGroupItem>
   </div>
 </template>
 
@@ -28,8 +32,13 @@ export default {
       type: Boolean,
       default: true
     },
+    articleId: {
+      type: [String, Number],
+    },
     share: Boolean,
-    thumb: Boolean
+    thumb: Boolean,
+    posId: Number,
+    index: Number
   },
   computed: {
     single() {
diff --git a/apps/components/widgets/widget-fav.vue b/apps/components/widgets/widget-fav.vue
index 46b84a0..54403f3 100644
--- a/apps/components/widgets/widget-fav.vue
+++ b/apps/components/widgets/widget-fav.vue
@@ -1,5 +1,5 @@
 <template>
-  <WidgetIconBtn type="fav" :share="share" :text="num" :article-id="articleId" :comment-id="commentId" :option="option"></WidgetIconBtn>
+  <WidgetIconBtn type="fav" :share="share" :text="num" :article-id="articleId" :comment-id="commentId" :option="option" :pos-id="posId"></WidgetIconBtn>
 </template>
 
 <script>
@@ -8,6 +8,7 @@ export default {
   props: {
     num: [String, Number],
     articleId: Number,
+    posId: Number,
     commentId: Number,
     option: Object,
     share: Boolean
diff --git a/apps/components/widgets/widget-follow.vue b/apps/components/widgets/widget-follow.vue
index fec3c33..34c1c17 100644
--- a/apps/components/widgets/widget-follow.vue
+++ b/apps/components/widgets/widget-follow.vue
@@ -6,6 +6,7 @@
 
 <script>
 import {createNamespacedHelpers} from 'vuex';
+import YAS from 'utils/yas-constants';
 const {mapActions} = createNamespacedHelpers('user');
 
 export default {
@@ -17,7 +18,8 @@ export default {
       type: [Number, String],
       default: 1
     },
-    share: Boolean
+    share: Boolean,
+    posId: Number
   },
   data() {
     return {
@@ -60,6 +62,9 @@ export default {
       this.loading = false;
       if (result.code === 200) {
         this.followStatus = !this.followStatus;
+        if (this.followStatus) {
+          this.reportFellow();
+        }
         this.$emit('on-follow', this.followStatus);
       } else {
         this.$createToast && this.$createToast({
@@ -68,6 +73,17 @@ export default {
           time: 1000
         }).show();
       }
+    },
+    reportFellow() {
+      this.$store.dispatch('reportYas', {
+        params: {
+          appop: YAS.eventName.fellow,
+          param: {
+            AUTH_ID: this.authorUid,
+            POS_ID: this.posId
+          }
+        }
+      });
     }
   }
 };
diff --git a/apps/components/widgets/widget-icon-btn.vue b/apps/components/widgets/widget-icon-btn.vue
index f82f7ce..b71ad44 100644
--- a/apps/components/widgets/widget-icon-btn.vue
+++ b/apps/components/widgets/widget-icon-btn.vue
@@ -15,6 +15,7 @@ import {createNamespacedHelpers} from 'vuex';
 const {mapActions} = createNamespacedHelpers('user');
 const {mapActions: articleMapActions} = createNamespacedHelpers('article');
 import cookie from 'yoho-cookie';
+import YAS from 'utils/yas-constants';
 
 const classMap = {
   fav: {
@@ -63,6 +64,7 @@ export default {
       }
     },
     articleId: Number,
+    posId: Number,
     commentId: Number,
     option: {
       type: Object,
@@ -96,6 +98,17 @@ export default {
         return 'praiseComment';
       }
     },
+    syncReportName() {
+      if (this.articleId) {
+        if (this.type === 'fav') {
+          return 'reportFav';
+        } else if (this.type === 'star') {
+          return 'reportStar';
+        }
+      }
+
+      return '';
+    },
     isAuth() {
       return !!this.syncFnName;
     },
@@ -141,7 +154,7 @@ export default {
     placText() {
       if (!isNaN(Number(this.text)) && this.viewText.length) {
         return fill(Array(this.viewText.length), 0).join('');
-      } else  {
+      } else {
         return `${this.text}`;
       }
     }
@@ -243,6 +256,8 @@ export default {
                 this.fetchArticleUpdate({articleId: this.articleId});
               }
             }
+
+            this[this.syncReportName] && this[this.syncReportName]();
           };
 
           this.syncing = true;
@@ -256,6 +271,32 @@ export default {
       }
 
       this.viewOption.emitName && this.$emit(this.viewOption.emitName, evt);
+    },
+    reportFav() {
+      if (this.viewOption.selected) {
+        this.$store.dispatch('reportYas', {
+          params: {
+            appop: YAS.eventName.fav,
+            param: {
+              POS_ID: this.posId,
+              ARTICLE_ID: this.articleId
+            }
+          }
+        });
+      }
+    },
+    reportStar() {
+      if (this.viewOption.selected) {
+        this.$store.dispatch('reportYas', {
+          params: {
+            appop: YAS.eventName.star,
+            param: {
+              POS_ID: this.posId,
+              ARTICLE_ID: this.articleId
+            }
+          }
+        });
+      }
     }
   },
 };
diff --git a/apps/components/widgets/widget-like.vue b/apps/components/widgets/widget-like.vue
index c87bdc5..fecbd3c 100644
--- a/apps/components/widgets/widget-like.vue
+++ b/apps/components/widgets/widget-like.vue
@@ -1,5 +1,5 @@
 <template>
-  <WidgetIconBtn type="star" :share="share" :text="num" :article-id="articleId" :comment-id="commentId" :option="option"></WidgetIconBtn>
+  <WidgetIconBtn type="star" :share="share" :text="num" :article-id="articleId" :comment-id="commentId" :option="option" :pos-id="posId"></WidgetIconBtn>
 </template>
 
 <script>
@@ -9,6 +9,7 @@ export default {
     num: [String, Number],
     articleId: Number,
     commentId: Number,
+    posId: Number,
     option: Object,
     share: Boolean
   }
diff --git a/apps/pages/article/article-comment.vue b/apps/pages/article/article-comment.vue
index 37146c4..aa5c573 100644
--- a/apps/pages/article/article-comment.vue
+++ b/apps/pages/article/article-comment.vue
@@ -1,15 +1,18 @@
 <template>
-  <Comment ref="comment" :dest-id="articleId"></Comment>
+  <Comment ref="comment" :dest-id="articleId" :pos-id="sceneId" :articleId="articleId"></Comment>
 </template>
 
 <script>
 
+import YAS from 'utils/yas-constants';
+
 export default {
   name: 'ArticleComment',
   data() {
     return {
       size: 0,
-      articleId: 0
+      articleId: 0,
+      sceneId: YAS.scene.newsDetail
     };
   },
   mounted() {
diff --git a/apps/pages/article/article.vue b/apps/pages/article/article.vue
index e2901a7..a4c7ef6 100644
--- a/apps/pages/article/article.vue
+++ b/apps/pages/article/article.vue
@@ -3,7 +3,9 @@
     ref="article"
     type="article"
     :thumbs="articleThumbList"
-    :on-fetch="onFetch">
+    :on-fetch="onFetch"
+    :pos-id="sceneId"
+  >
   </Article>
 </template>
 
@@ -12,6 +14,7 @@ import {get} from 'lodash';
 import Article from './components/article/article';
 import ArticleItem from './components/article/article-item';
 import {createNamespacedHelpers} from 'vuex';
+import YAS from 'utils/yas-constants';
 const {mapState, mapActions} = createNamespacedHelpers('article');
 
 export default {
@@ -20,6 +23,7 @@ export default {
     return {
       page: 1,
       id: 0,
+      sceneId: YAS.scene.list
     };
   },
   created() {
diff --git a/apps/pages/article/components/article/article-item-comment.vue b/apps/pages/article/components/article/article-item-comment.vue
index 2b37a15..c61e018 100644
--- a/apps/pages/article/components/article/article-item-comment.vue
+++ b/apps/pages/article/components/article/article-item-comment.vue
@@ -7,6 +7,8 @@
       v-for="(comment, inx) in data.comments"
       :key="inx"
       :dest-id="comment.id"
+      :pos-id="posId"
+      :article-id="articleId"
       :add-type="1"
       :column-type="comment.columnType"
       :user="comment.userName">
@@ -19,6 +21,8 @@
         class="comment-input hover-opacity"
         :dest-id="data.articleId"
         :add-type="0"
+        :article-id="articleId"
+        :pos-id="posId"
         :column-type="1001"
         @on-comment="onComment">
         添加评论
@@ -46,7 +50,9 @@ export default {
     },
     type: String,
     share: Boolean,
-    thumb: Boolean
+    thumb: Boolean,
+    posId: Number,
+    articleId: [Number, String]
   },
   computed: {
     ...mapState(['articleStates']),
diff --git a/apps/pages/article/components/article/article-item-header.vue b/apps/pages/article/components/article/article-item-header.vue
index a1215ce..e6c0878 100644
--- a/apps/pages/article/components/article/article-item-header.vue
+++ b/apps/pages/article/components/article/article-item-header.vue
@@ -12,6 +12,8 @@
 </template>
 
 <script>
+import YAS from 'utils/yas-constants';
+
 export default {
   name: 'ArticleItemHeader',
   props: {
@@ -27,7 +29,8 @@ export default {
     },
     type: String,
     share: Boolean,
-    thumb: Boolean
+    thumb: Boolean,
+    posId: Number
   },
   computed: {
     invisibleClass() {
@@ -44,6 +47,7 @@ export default {
       if (this.share) {
         return this.$links.toDownloadApp();
       }
+
       this.$router.push({
         name: 'author',
         params: {
@@ -51,9 +55,22 @@ export default {
           id: this.data.authorUid
         }
       });
+
+      this.reportClickAvatar();
     },
     onFollow(follow) {
       this.$emit('on-follow', follow);
+    },
+    reportClickAvatar() {
+      this.$store.dispatch('reportYas', {
+        params: {
+          appop: YAS.eventName.avatar,
+          param: {
+            AUTH_ID: this.data.authorUid,
+            POS_ID: this.posId
+          }
+        }
+      });
     }
   }
 };
diff --git a/apps/pages/article/components/article/article-item-intro.vue b/apps/pages/article/components/article/article-item-intro.vue
index c2a7c35..7b4f53e 100644
--- a/apps/pages/article/components/article/article-item-intro.vue
+++ b/apps/pages/article/components/article/article-item-intro.vue
@@ -20,8 +20,8 @@
         <WidgetShare :share="share" @click.native="onShare"></WidgetShare>
       </div>
       <div class="opts">
-        <WidgetFav :class="invisibleClass" :share="share" :num="articleState.praiseCount" :article-id="data.articleId" :option="praiseOption"></WidgetFav>
-        <WidgetLike :class="invisibleClass" :share="share" :num="articleState.favoriteCount" :article-id="data.articleId" :option="favoriteOption"></WidgetLike>
+        <WidgetFav :class="invisibleClass" :share="share" :num="articleState.praiseCount" :article-id="data.articleId" :option="praiseOption" :pos-id="posId"></WidgetFav>
+        <WidgetLike :class="invisibleClass" :share="share" :num="articleState.favoriteCount" :article-id="data.articleId" :option="favoriteOption" :pos-id="posId"></WidgetLike>
         <WidgetComment :class="invisibleClass" :share="share" :num="articleState.commentCount" @click.native="onShowComment"></WidgetComment>
       </div>
     </div>
@@ -31,6 +31,7 @@
 <script>
 import {get} from 'lodash';
 import {createNamespacedHelpers} from 'vuex';
+import YAS from 'utils/yas-constants';
 const {mapMutations, mapState} = createNamespacedHelpers('article');
 
 export default {
@@ -44,7 +45,8 @@ export default {
     },
     type: String,
     share: Boolean,
-    thumb: Boolean
+    thumb: Boolean,
+    posId: Number
   },
   data() {
     return {
@@ -134,6 +136,7 @@ export default {
       if (this.data.articleType === 5) {
         return;
       }
+
       this.$router.push({
         name: 'topic',
         params: {
@@ -141,6 +144,8 @@ export default {
           labelName: labelName
         }
       });
+
+      this.reportLabel(labelId);
     },
     onShare() {
       let title = `@${this.data.authorName} 在有货逛上发了一篇笔记,快点开看看!`;
@@ -179,6 +184,17 @@ export default {
       if (this.articleState.commentCount) {
         this.$emit('on-show-comment');
       }
+    },
+    reportLabel(id) {
+      this.$store.dispatch('reportYas', {
+        params: {
+          appop: YAS.eventName.labelClick,
+          param: {
+            AUTH_ID: id,
+            POS_ID: this.posId
+          }
+        }
+      });
     }
   }
 };
diff --git a/apps/pages/article/components/article/article-item.vue b/apps/pages/article/components/article/article-item.vue
index b099ac4..3605a05 100644
--- a/apps/pages/article/components/article/article-item.vue
+++ b/apps/pages/article/components/article/article-item.vue
@@ -1,10 +1,12 @@
 <template>
   <div class="article-item">
-    <ArticleItemHeader :type="type" :thumb="thumb" :share="share" :data="headerData" :lazy="lazy" @on-follow="onFollow" @on-show-more="onShowMore"></ArticleItemHeader>
+    <ArticleItemHeader :pos-id="posId" :type="type" :thumb="thumb" :share="share" :data="headerData" :lazy="lazy" @on-follow="onFollow" @on-show-more="onShowMore"></ArticleItemHeader>
     <ArticleItemSlide :type="type" :thumb="thumb" :share="share" :data="slideData" :slide-index="data.blockIndex" :lazy="lazy"></ArticleItemSlide>
-    <ProductGroup :thumb="thumb" v-if="productListData.length" :share="share" :data="productListData" :lazy="lazy"></ProductGroup>
-    <ArticleItemIntro :thumb="thumb" :type="type" :share="share" :data="introData" @on-expand="onExpand" @on-expanding="onExpanding" @on-show-guang="onShowGuang" @on-show-comment="onShowComment"></ArticleItemIntro>
-    <ArticleItemComment :thumb="thumb" :type="type" :share="share" :data="commentData" @on-show-comment="onShowComment" @on-resize="onResize"></ArticleItemComment>
+    <ProductGroup :article-id="data.articleId" :pos-id="posId" :index="index" :thumb="thumb" v-if="productListData.length" :share="share" :data="productListData" :lazy="lazy"></ProductGroup>
+    <ArticleItemIntro :thumb="thumb" :type="type" :share="share" :data="introData" @on-expand="onExpand" @on-expanding="onExpanding" @on-show-guang="onShowGuang" @on-show-comment="onShowComment"
+    :article-id="articleId" :pos-id="posId">
+    </ArticleItemIntro>
+    <ArticleItemComment :thumb="thumb" :type="type" :share="share" :data="commentData" @on-show-comment="onShowComment" @on-resize="onResize" :pos-id="posId" :article-id="articleId" ></ArticleItemComment>
     <div class="line"></div>
   </div>
 </template>
@@ -15,6 +17,7 @@ import ArticleItemHeader from './article-item-header';
 import ArticleItemSlide from './article-item-slide';
 import ArticleItemIntro from './article-item-intro';
 import ArticleItemComment from './article-item-comment';
+import YAS from 'utils/yas-constants';
 import dayjs from 'dayjs';
 
 export default {
@@ -29,7 +32,9 @@ export default {
     index: Number,
     share: Boolean,
     type: String,
-    thumb: Boolean
+    thumb: Boolean,
+    posId: Number,
+    articleId: Number
   },
   computed: {
     articleState() {
@@ -101,18 +106,45 @@ export default {
           this.changeResolve = r;
         })
       });
+      this.reportClickArticle();
     },
     onFollow(follow) {
       this.$emit('on-follow', follow);
     },
     onShowGuang() {
       this.$emit('on-show-guang', {articleId: this.data.relateId, grassId: this.data.articleId});
+      this.reportOpenGuang();
     },
     onShowComment() {
       this.$emit('on-show-comment', {articleId: this.data.articleId, index: this.index});
     },
     onShowMore() {
       this.$emit('on-show-more', {article: this.data, index: this.index});
+    },
+    reportOpenGuang() {
+      this.$store.dispatch('reportYas', {
+        params: {
+          appop: 'YB_H5_PAGE_OPEN_L',
+          param: {
+            F_URL: `${location.origin}/news/${this.articleId}`,
+            PAGE_URL: '',
+            PAGE_NAME: 'news'
+          }
+        }
+      });
+    },
+    reportClickArticle() {
+      this.$store.dispatch('reportYas', {
+        params: {
+          appop: YAS.eventName.articleExpand,
+          param: {
+            I_INDEX: this.index,
+            ARTICLE_ID: this.articleId,
+            PRD_SKN: this.productListData.map(i => i.productSkn).join(','),
+            POS_ID: this.posId
+          }
+        }
+      });
     }
   },
   components: {ArticleItemHeader, ArticleItemSlide, ArticleItemIntro, ArticleItemComment}
diff --git a/apps/pages/article/components/article/article.vue b/apps/pages/article/components/article/article.vue
index e36f74a..7718d8a 100644
--- a/apps/pages/article/components/article/article.vue
+++ b/apps/pages/article/components/article/article.vue
@@ -9,7 +9,7 @@
           </div>
         </template>
         <template v-if="showHeader" v-slot:opts>
-          <WidgetFollow :share="share" class="widget-follow" :author-uid="currentAuthor.authorUid" :follow="currentAuthor.hasAttention === 'Y'" @on-follow="follow => onFollow(currentAuthor, follow)"></WidgetFollow>
+          <WidgetFollow :share="share" class="widget-follow" :author-uid="currentAuthor.authorUid" :follow="currentAuthor.hasAttention === 'Y'" @on-follow="follow => onFollow(currentAuthor, follow)" :pos-id="posId"></WidgetFollow>
         </template>
       </LayoutHeader>
       <LayoutRecycleList :size="10" :thumbs="thumbs" ref="scroll" @scroll="onScroll" :offset="2000" :on-fetch="onFetch">
@@ -19,6 +19,8 @@
             :index="data.index"
             :data="data.data"
             :share="share"
+            :article-id="data.articleId"
+            :pos-id="posId"
             @on-follow="follow => onFollow(data.data, follow)"
             @on-resize="onResize"
             @on-unlock-height="onUnlockHeight"
@@ -33,6 +35,8 @@
       <Comment ref="comment"
         :destId="articleId"
         :popup="true"
+        :article-id="articleId"
+        :pos-id="posId"
         @on-close="onClose"
         @on-comment="onActionComment"
         @on-page-ready="onPageReady"></Comment>
@@ -43,6 +47,7 @@
 
 <script>
 import {throttle} from 'lodash';
+import YAS from 'utils/yas-constants';
 import ArticleItem from './article-item';
 import ArticleActionSheet from '../detail/article-action-sheet';
 import MoreActionSheet from '../detail/more-action-sheet';
@@ -65,10 +70,12 @@ export default {
       default() {
         return [];
       }
-    }
+    },
+    posId: Number
   },
   mounted() {
     this.scrollEvent = throttle(this.onDounceScroll.bind(this), 100);
+    this.reportShow = this.startReportShow();
   },
   data() {
     return {
@@ -106,6 +113,7 @@ export default {
       if (this.share) {
         return this.$links.toDownloadApp();
       }
+
       this.$router.push({
         name: 'author',
         params: {
@@ -113,6 +121,8 @@ export default {
           id: this.currentAuthor.authorUid
         }
       });
+
+      this.reportClickAvatar();
     },
     onShowComment({articleId, index}) {
       this.articleId = articleId;
@@ -161,7 +171,7 @@ export default {
     onScroll(params) {
       this.scrollEvent(params);
     },
-    onDounceScroll({item, scrollTop}) {
+    onDounceScroll({item, scrollTop, startIndex}) {
       this.scrollTop = scrollTop;
       if (scrollTop === 0) {
         this.showHeader = false;
@@ -177,6 +187,8 @@ export default {
         this.currentAuthor.authorType = item.data.authorType;
 
         this.showHeader = true;
+
+        this.reportShow(startIndex, item);
       }
     },
     init() {
@@ -199,6 +211,42 @@ export default {
       this.$nextTick(() => {
         this.$refs.actionSheet.show(params);
       });
+    },
+    reportClickAvatar() {
+      this.$store.dispatch('reportYas', {
+        params: {
+          appop: YAS.eventName.avatar,
+          param: {
+            AUTH_ID: this.currentAuthor.authorUid,
+            POS_ID: this.posId
+          }
+        }
+      });
+    },
+    startReportShow() {
+      let preview = null;
+
+      return (index, item) => {
+        if (preview === item.data.articleId) {
+          return;
+        }
+
+        preview = item.data.articleId;
+
+        this.$store.dispatch('reportYas', {
+          params: {
+            appop: YAS.eventName.show,
+            param: {
+              P_NAME: this.$route.name,
+              P_PARAM: this.$route.params,
+              I_INDEX: index,
+              ARTICLE_ID: preview,
+              PRD_SKN: (item.data.productList || []).map(i => i.productSkn).join(','),
+              POS_ID: this.posId
+            }
+          }
+        });
+      };
     }
   },
   components: {
diff --git a/apps/pages/article/components/detail/article-author.vue b/apps/pages/article/components/detail/article-author.vue
index 48bbc06..1276ee2 100644
--- a/apps/pages/article/components/detail/article-author.vue
+++ b/apps/pages/article/components/detail/article-author.vue
@@ -1,9 +1,9 @@
 <template>
   <div class="article-item-header">
-    <router-link class="avatar" :to="`/grass/author/${data.authorType}/${data.authorUid}`">
+    <div class="avatar" @click="goAuthor">
       <WidgetAvatar class="widget-avatar" :src="data.avatar" :width="70" :height="70"></WidgetAvatar>
       <span class="name">{{data.name}}</span>
-    </router-link>
+    </div>
     <div class="opts">
       <WidgetFollow v-bind="data"></WidgetFollow>
     </div>
@@ -11,6 +11,9 @@
 </template>
 
 <script>
+
+import YAS from 'utils/yas-constants';
+
 export default {
   name: 'ArticleAuthor',
   props: {
@@ -19,9 +22,32 @@ export default {
       default() {
         return {};
       }
-    }
+    },
+    posId: Number
   },
   methods: {
+    goAuthor() {
+      this.$router.push({
+        name: 'author',
+        params: {
+          type: this.data.authorType,
+          id: this.data.authorUid
+        }
+      });
+
+      this.reportClickAvatar();
+    },
+    reportClickAvatar() {
+      this.$store.dispatch('reportYas', {
+        params: {
+          appop: YAS.eventName.avatar,
+          param: {
+            AUTH_ID: this.data.authorUid,
+            POS_ID: this.posId
+          }
+        }
+      });
+    }
   }
 };
 </script>
diff --git a/apps/pages/article/components/detail/article-body.vue b/apps/pages/article/components/detail/article-body.vue
index 1d10dc6..8228164 100644
--- a/apps/pages/article/components/detail/article-body.vue
+++ b/apps/pages/article/components/detail/article-body.vue
@@ -1,6 +1,6 @@
 <template>
     <div class="scroll-wrapper">
-      <Author :data="articleDetail.getAuthor"></Author>
+      <Author :data="articleDetail.getAuthor" :pos-id="sceneId"></Author>
       <div class="post-content" v-if="articleDetail && articleDetail.getArticleContent">
         <template v-for="item in articleDetail.getArticleContent">
           <template v-if="item.text">
@@ -23,7 +23,7 @@
           </template>
           <template v-if="item.relatedReco">
             <div class="products">
-              <ProductGroup v-for="(p,index) in item.relatedReco.goods" :data="[p]" :key="index"></ProductGroup>
+              <ProductGroup :pos-id="sceneId" :article-id="articleId" v-for="(p,index) in item.relatedReco.goods" :data="[p]" :key="index"></ProductGroup>
             </div>
           </template>
         </template>
@@ -44,11 +44,13 @@ import Author from './article-author';
 import ZanBar from './zan-bar';
 import TagBar from './tag-bar';
 import { createNamespacedHelpers } from 'vuex';
+import YAS from 'utils/yas-constants';
 
 const { mapState } = createNamespacedHelpers('article');
 
 export default {
   name: 'ArticleBody',
+  props: ['articleId'],
   components: {
     RecommendProductList,
     Recommend,
@@ -61,7 +63,8 @@ export default {
       scrollOpts: {
         eventPassthrough: 'horizontal',
         bounce: false
-      }
+      },
+      sceneId: YAS.scene.newsDetail
     };
   },
   computed: {
diff --git a/apps/pages/article/components/detail/article-detail.vue b/apps/pages/article/components/detail/article-detail.vue
index eb624c4..7d88dde 100644
--- a/apps/pages/article/components/detail/article-detail.vue
+++ b/apps/pages/article/components/detail/article-detail.vue
@@ -5,7 +5,7 @@
     <div class="body" v-if="fetchStatus">
       <Loading class="loading"></Loading>
     </div>
-    <ArticleBody v-else ref="body" class="body"></ArticleBody>
+    <ArticleBody v-else ref="body" :articleId="grassId" class="body"></ArticleBody>
 
     <ArticleFooter class="footer"
        v-if="articleDetail"
@@ -23,6 +23,7 @@ import ArticleFooter from './article-footer';
 import ArticleBody from './article-body';
 import * as sleep from '../../../../utils/sleep';
 import { createNamespacedHelpers } from 'vuex';
+import YAS from 'utils/yas-constants';
 import { Loading } from 'cube-ui';
 
 const { mapActions, mapState, mapMutations } = createNamespacedHelpers('article');
@@ -38,7 +39,8 @@ export default {
   data() {
     return {
       articleId: 0,
-      grassId: 0
+      grassId: 0,
+      posId: YAS.scene.newsDetail
     };
   },
   mounted() {
@@ -52,9 +54,10 @@ export default {
         }
       });
     },
-    ...mapActions(['getDetail']),
+    ...mapActions(['getDetail', 'fetchProductFav']),
     ...mapMutations({
-      fetchArticleDetail: 'FETCH_GUANG_SUCCESS'
+      fetchArticleDetail: 'FETCH_GUANG_SUCCESS',
+      fetchArticleProductList: 'GUANG_DETAIL_PRODUCT_LIST'
     }),
     fetch(params) {
       this.articleId = params.articleId;
@@ -63,6 +66,12 @@ export default {
       return this.getDetail({
         article_id: params.articleId,
         grass_id: params.grassId
+      }).then(() => {
+        this.$sdk.getUser().then(user => {
+          if (user && user.uid) {
+            this.fetchProductFav();
+          }
+        });
       });
     },
     onClose() {
@@ -72,6 +81,7 @@ export default {
     async reset() {
       await sleep.sleep(200);
       this.fetchArticleDetail({});
+      this.fetchArticleProductList([]);
     }
   },
   computed: {
diff --git a/apps/pages/article/components/detail/article-footer.vue b/apps/pages/article/components/detail/article-footer.vue
index d0f9bfe..12d87ae 100644
--- a/apps/pages/article/components/detail/article-footer.vue
+++ b/apps/pages/article/components/detail/article-footer.vue
@@ -1,8 +1,8 @@
 <template>
   <div class="article-footer-wrapper">
     <div class="tool-bar">
-      <WidgetIconBtn class="item" type="fav" :text="praiseCount" :articleId="articleId" :option="optionPraise"></WidgetIconBtn>
-      <WidgetIconBtn class="item" type="star" :text="favoriteCount" :articleId="articleId" :option="optionFav" ></WidgetIconBtn>
+      <WidgetIconBtn class="item" type="fav" :pos-id="sceneId" :text="praiseCount" :articleId="articleId" :option="optionPraise"></WidgetIconBtn>
+      <WidgetIconBtn class="item" type="star" :pos-id="sceneId" :text="favoriteCount" :articleId="articleId" :option="optionFav" ></WidgetIconBtn>
       <WidgetIconBtn class="item" type="msg" :text="commentCount" :option="optionComment" @click="onComment"></WidgetIconBtn>
     </div>
     <div class="close ml20" @click="onClose">收起</div>
@@ -11,6 +11,8 @@
 
 <script>
 
+import YAS from 'utils/yas-constants';
+
 export default {
   name: 'ArticleFooter',
   props: ['favoriteCount', 'praiseCount', 'commentCount', 'hasFavor', 'hasPraise', 'articleId'],
@@ -26,6 +28,7 @@ export default {
         emitName: 'click',
         canSelect: false
       },
+      sceneId: YAS.scene.newsDetail
     };
   },
   computed: {
diff --git a/apps/pages/article/topic.vue b/apps/pages/article/topic.vue
index bc41981..2d7a42b 100644
--- a/apps/pages/article/topic.vue
+++ b/apps/pages/article/topic.vue
@@ -3,7 +3,9 @@
     ref="article"
     :title="labelName"
     type="topic"
-    :on-fetch="onFetch">
+    :on-fetch="onFetch"
+    :pos-id="sceneId"
+  >
   </Article>
 </template>
 
@@ -12,6 +14,7 @@ import {get} from 'lodash';
 import Article from './components/article/article';
 import ArticleItem from './components/article/article-item';
 import {createNamespacedHelpers} from 'vuex';
+import YAS from 'utils/yas-constants';
 const {mapActions} = createNamespacedHelpers('article');
 
 export default {
@@ -22,6 +25,7 @@ export default {
       labelId: 0,
       reload: true,
       labelName: '',
+      sceneId: YAS.scene.topicList
     };
   },
   created() {
diff --git a/apps/pages/article/user-article.vue b/apps/pages/article/user-article.vue
index c693741..073e8ae 100644
--- a/apps/pages/article/user-article.vue
+++ b/apps/pages/article/user-article.vue
@@ -4,7 +4,8 @@
     :title="userName"
     type="userArticle"
     :thumbs="articleUserThumbList"
-    :on-fetch="onFetch">
+    :on-fetch="onFetch"
+    :pos-id="sceneId">
   </Article>
 </template>
 
@@ -13,6 +14,7 @@ import {get} from 'lodash';
 import Article from './components/article/article';
 import ArticleItem from './components/article/article-item';
 import {createNamespacedHelpers} from 'vuex';
+import YAS from 'utils/yas-constants';
 const {mapState, mapActions} = createNamespacedHelpers('article');
 
 export default {
@@ -24,7 +26,8 @@ export default {
       authorUid: 0,
       authorType: 0,
       type: '',
-      userName: ''
+      userName: '',
+      sceneId: YAS.scene.authorList
     };
   },
   created() {
diff --git a/apps/pages/userpage/author.vue b/apps/pages/userpage/author.vue
index e0cd4a8..06376df 100644
--- a/apps/pages/userpage/author.vue
+++ b/apps/pages/userpage/author.vue
@@ -11,7 +11,7 @@
             <WidgetAvatar class="h-headico" :src="authorBaseData.headIco" :width="100" :height="100"></WidgetAvatar>
           </div>
           <div v-if="!isOwner" class="h-follow flex">
-            <WidgetFollow class="widget-follow" :author-uid="autherInfo.authorUid" :follow="authorBaseData.hasAttention === 'Y'" @on-follow="follow => onFollow(follow)"></WidgetFollow>
+            <WidgetFollow class="widget-follow" :author-uid="autherInfo.authorUid" :follow="authorBaseData.hasAttention === 'Y'" @on-follow="follow => onFollow(follow)" :pos-id="sceneId"></WidgetFollow>
           </div>
         </div>
       </div>
@@ -42,7 +42,7 @@
           </ul>
           <div class="operate-wrap">
             <a v-if="isOwner" class="operate-btn btn-user-edit" :href="mineInfoUrl">编辑个人资料</a>
-            <WidgetFollow v-if="!isOwner && authorBaseData.hasAttention" class="operate-btn" :author-uid="autherInfo.authorUid" :follow="authorBaseData.hasAttention === 'Y'" @on-follow="follow => onFollow(follow)"></WidgetFollow>
+            <WidgetFollow v-if="!isOwner && authorBaseData.hasAttention" class="operate-btn" :author-uid="autherInfo.authorUid" :follow="authorBaseData.hasAttention === 'Y'" @on-follow="follow => onFollow(follow)" :pos-id="sceneId"></WidgetFollow>
           </div>
         </div>
       </div>
@@ -52,7 +52,7 @@
       </div>
       <div ref="contantList" class="contant-list" :style="`min-height: ${listMinHeight}px;`">
         <p v-if="emptyTip" class="empty-tip">{{emptyTip}}</p>
-        <WaterFall class="pannel-wrap" :list="list" :params="params"></WaterFall>
+        <WaterFall class="pannel-wrap" :list="list" :params="params" :tab="activeIndex"></WaterFall>
         <div v-if="loadStatus && !emptyTip" class="loading">
           <Loading v-if="loadStatus === 1" class="load-icon" :size="20"></Loading>
           <p v-else class="load-text">没有更多了</p>
@@ -69,6 +69,7 @@ import {assign, get} from 'lodash';
 import {Scroll, Loading} from 'cube-ui';
 import FavTabBlock from './components/fav-tab-block';
 import WaterFall from './components/scroll-reveal';
+import YAS from 'utils/yas-constants';
 
 import {createNamespacedHelpers} from 'vuex';
 const {mapState, mapActions, mapMutations} = createNamespacedHelpers('user');
@@ -96,7 +97,8 @@ export default {
       emptyTip: '',
       scrollOpts: {
         bounce: false,
-      }
+      },
+      sceneId: YAS.scene.author
     };
   },
   created() {
diff --git a/apps/pages/userpage/components/author-article-item.vue b/apps/pages/userpage/components/author-article-item.vue
index 2e5d96e..1d93460 100644
--- a/apps/pages/userpage/components/author-article-item.vue
+++ b/apps/pages/userpage/components/author-article-item.vue
@@ -18,7 +18,7 @@
         </div>
 
         <div class="fav">
-          <WidgetFav :articleId="data.articleId" :num="data.praiseCount" :option="favOption"></WidgetFav>
+          <WidgetFav :articleId="data.articleId" :num="data.praiseCount" :option="favOption" :pos-id="sceneId"></WidgetFav>
         </div>
       </div>
     </div>
@@ -27,11 +27,13 @@
 
 
 <script>
+import YAS from 'utils/yas-constants';
 export default {
   data() {
     return {
-      imgWidth: 350
-    }
+      imgWidth: 350,
+      sceneId: YAS.scene.author
+    };
   },
   props: {
     data: {
@@ -43,7 +45,9 @@ export default {
     temporary: {
       type: Boolean,
       default: false
-    }
+    },
+    index: Number,
+    tab: Number
   },
   computed: {
     favOption() {
@@ -52,13 +56,28 @@ export default {
         iconBold: true,
         iconFontSize: 26,
         textAlign: 'normal'
-      }
+      };
     }
   },
   methods: {
     onClick(type) {
+      if (type === 'article') {
+        this.reportClickArticle();
+      }
       this.$emit('click', {data: this.data, type});
-    }
+    },
+    reportClickArticle() {
+      this.$store.dispatch('reportYas', {
+        params: {
+          appop: YAS.eventName.articleExpand,
+          param: {
+            I_INDEX: this.index,
+            ARTICLE_ID: this.data.articleId,
+            POS_ID: this.posId
+          }
+        }
+      });
+    },
   }
 };
 </script>
diff --git a/apps/pages/userpage/components/scroll-reveal.vue b/apps/pages/userpage/components/scroll-reveal.vue
index 63381ac..c1edfa8 100644
--- a/apps/pages/userpage/components/scroll-reveal.vue
+++ b/apps/pages/userpage/components/scroll-reveal.vue
@@ -2,9 +2,9 @@
   <div class="sr-list">
     <div class="sr-col" v-for="(col, index) in colsList" :key="index" :style="`width:${100/cols}%`">
       <template v-if="col.length">
-        <ArticleItem v-for="item in col" :key="item.articleId" class="sr-item" :data="item" @click="onClick"></ArticleItem>
+        <ArticleItem v-for="(item, index) in col" :key="item.articleId" class="sr-item" :data="item" :index="index" @click="onClick"  :tab="tab"></ArticleItem>
       </template>
-      <ArticleItem class="sr-temp" :temporary="true"></ArticleItem>
+      <ArticleItem class="sr-temp" :temporary="true" :index="0" :tab="tab"></ArticleItem>
     </div>
   </div>
 </template>
@@ -32,7 +32,8 @@ export default {
       type: Number,
       default: 2
     },
-    params: Object
+    params: Object,
+    tab: Number
   },
   created() {
     this.reset();
@@ -140,7 +141,7 @@ export default {
     },
     onClick({data, type}) {
       if (type === 'author') {
-        this.toAuthor(data)
+        this.toAuthor(data);
       } else {
         this.toArticle(data);
       }
@@ -176,7 +177,7 @@ export default {
               this.$router.push(router);
             }
           });
-        } catch(e){
+        } catch (e) {
           console.log(e);
         }
       } else {
diff --git a/apps/store/article/actions.js b/apps/store/article/actions.js
index 554c8d1..3056f43 100644
--- a/apps/store/article/actions.js
+++ b/apps/store/article/actions.js
@@ -170,33 +170,28 @@ export default {
 
     await sleep.sleep(200);
     commit(Types.GUANG_ARTICLE_CONTENT, processContents.finalDetail);
+    commit(Types.GUANG_DETAIL_PRODUCT_LIST, processContents.allgoods);
 
     //再处理其他信息
-    const [goodsList, favsList, zan, article] = await Promise.all([
+    const [goodsList, zan, article] = await Promise.all([
       this.$api.post('/api/guang/article/queryGoods', {
         query: processContents.allgoods.skn.join(','),
         order: 's_t_desc',
         limit: processContents.allgoods.skn.length || 1
       }),
-      this.$api.post('/api/favorite/batchCheckIsFavorite', {
-        favIds: processContents.allgoods.id.join(','),
-        type: 'product'
-      }),
       this.$api.post('/api/guang/article/zan', { articleId: grass_id }),
       this.$api.get('/api/guang/article/detail', { article_id })
-    ]).then(([res1, res2, res3, res4]) => {
+    ]).then(([res1, res2, res3]) => {
       return [
         get(res1, 'data.product_list', []),
-        get(res2, 'data', []),
-        get(res3, 'data', false),
-        get(res4, 'data', false)
+        get(res2, 'data', false),
+        get(res3, 'data', false)
       ];
     });
 
     result.getArticleContent = guangProcess.pushGoodsInfo(
       processContents.finalDetail,
-      goodsList,
-      favsList
+      goodsList
     );
 
     result.getRecommendProducts = processContents.recommends;
@@ -222,10 +217,21 @@ export default {
     }
 
     // 等待动画完成后,提交数据
-
-
     commit(Types.FETCH_GUANG_SUCCESS, result);
   },
+  async fetchProductFav({ commit, state }) {
+    if (!state.articleProductList.id.length) {
+      return;
+    }
+    const favsList = await this.$api.post('/api/favorite/batchCheckIsFavorite', {
+      favIds: state.articleProductList.id.join(','),
+      type: 'product'
+    }).then(result => {
+      return get(result, 'data', []);
+    });
+
+    commit(Types.GUANG_CHANGE_PRODUCT_FAV, favsList);
+  },
   async reportArticle(actions, {articleId}) {
     const result = await this.$api.post('/api/grass/reportIllegalArticle', {articleId});
 
diff --git a/apps/store/article/guangProcess.js b/apps/store/article/guangProcess.js
index a228ad0..935e173 100644
--- a/apps/store/article/guangProcess.js
+++ b/apps/store/article/guangProcess.js
@@ -237,8 +237,8 @@ export function processArticleDetail(articleContent) {
 /**
  * 商品搜索商品数据处理
  */
-function processProductList(list, favsList) {
-  const pruductList = [];
+function processProductList(list) {
+  const productList = [];
 
   forEach(list, (product) => {
     if (!product) {
@@ -269,7 +269,7 @@ function processProductList(list, favsList) {
           product.data.shopUrl = '//m.yohobuy.com/product/shop?domain=' + product.data.shop_domain;
         }
 
-        pruductList.push(product);
+        productList.push(product);
       }
 
       return;
@@ -286,6 +286,7 @@ function processProductList(list, favsList) {
     product.salesPrice = product.sales_price;
     product.productName = product.product_name;
     product.productId = product.product_id;
+    product.productSkn = product.product_skn;
 
     product.is_soon_sold_out = product.is_soon_sold_out === 'Y';
 
@@ -293,12 +294,9 @@ function processProductList(list, favsList) {
       product.cn_alphabet = productNameProcess(product.cn_alphabet);
     }
 
-    // fav
-    const fav = favsList.find(i => `${i.id}` === `${product.product_id}`);
-
     product.id = product.product_id;
     product.productType = 1;
-    product.favorite = get(fav, 'favorite', false);
+    product.favorite = false;
 
     /**
      * 全球购商品标记
@@ -320,10 +318,10 @@ function processProductList(list, favsList) {
       product.url = productUrl(product.product_skn);
     }
 
-    pruductList.push(product);
+    productList.push(product);
   });
 
-  return pruductList;
+  return productList;
 }
 
 const _goodsArrayToObj = (goodsArray) => {
@@ -335,8 +333,8 @@ const _goodsArrayToObj = (goodsArray) => {
 /**
  * 重新获取商品数据
  */
-export function pushGoodsInfo(finalDetail, goodsList, favsList) {
-  let goodsObj = _goodsArrayToObj(processProductList(goodsList, favsList));
+export function pushGoodsInfo(finalDetail, goodsList) {
+  let goodsObj = _goodsArrayToObj(processProductList(goodsList));
 
   finalDetail = cloneDeep(finalDetail);
 
diff --git a/apps/store/article/index.js b/apps/store/article/index.js
index ee958d9..3318965 100644
--- a/apps/store/article/index.js
+++ b/apps/store/article/index.js
@@ -15,6 +15,7 @@ export default function() {
       articleUserThumbList: [],
       fetchArticleDetail: false,
       articleDetail: {},
+      articleProductList: [],
       articleLastedTimeByTopic: 0,
       articleStates: {}
     },
diff --git a/apps/store/article/mutations.js b/apps/store/article/mutations.js
index b6b322e..f5caf94 100644
--- a/apps/store/article/mutations.js
+++ b/apps/store/article/mutations.js
@@ -194,5 +194,19 @@ export default {
   [Types.FETCH_GUANG_SUCCESS](state, data) {
     state.fetchArticleDetail = false;
     state.articleDetail = data;
+  },
+  [Types.GUANG_DETAIL_PRODUCT_LIST](state, data) {
+    state.articleProductList = data;
+  },
+  [Types.GUANG_CHANGE_PRODUCT_FAV](state, favsList) {
+    get(state.articleDetail, 'getArticleContent', []).forEach(c => {
+      const products = get(c, 'relatedReco.goods', []);
+
+      products.forEach(p => {
+        const fav = favsList.find(i => `${i.id}` === `${p.product_id}`);
+
+        p.favorite = get(fav, 'favorite', false);
+      });
+    });
   }
 };
diff --git a/apps/store/article/types.js b/apps/store/article/types.js
index a1e4343..992b336 100644
--- a/apps/store/article/types.js
+++ b/apps/store/article/types.js
@@ -18,6 +18,8 @@ export const FETCH_GUANG_SUCCESS = 'FETCH_GUANG_SUCCESS';
 export const FETCH_FAV_SUCCESS = 'FETCH_FAV_SUCCESS';
 export const FETCH_ZAN_SUCCESS = 'FETCH_ZAN_SUCCESS';
 export const GUANG_ARTICLE_CONTENT = 'GUANG_ARTICLE_CONTENT';
+export const GUANG_CHANGE_PRODUCT_FAV = 'GUANG_CHANGE_PRODUCT_FAV';
+export const GUANG_DETAIL_PRODUCT_LIST = 'GUANG_DETAIL_PRODUCT_LIST';
 
 export const CHANGE_AUTHOR_FOLLOW = 'CHANGE_AUTHOR_FOLLOW';
 export const CHANGE_ARTICLE_LIST_SLIDE = 'CHANGE_ARTICLE_LIST_SLIDE';
diff --git a/apps/store/yoho/index.js b/apps/store/yoho/index.js
index dab8d71..245907b 100644
--- a/apps/store/yoho/index.js
+++ b/apps/store/yoho/index.js
@@ -84,26 +84,30 @@ export default function() {
     },
     actions: {
       reportYas(params, {params: {appop, param}, asyncindx = false}) {
-        document.addEventListener('deviceready', () => {
-          setTimeout(() => {
-            if (window._yas && window._yas.sendAppLogs) {
-              param = param || {};
+        try {
+          document.addEventListener('deviceready', () => {
+            setTimeout(() => {
+              if (window._yas && window._yas.sendAppLogs) {
+                param = param || {};
 
-              if (!param.C_ID) {
-                const channel = {
-                  men: 1,
-                  women: 2
-                }[cookie.get('_Channel') || 'men'];
+                if (!param.C_ID) {
+                  const channel = {
+                    men: 1,
+                    women: 2
+                  }[cookie.get('_Channel') || 'men'];
 
-                param.C_ID = channel;
+                  param.C_ID = channel;
+                }
+                window._yas.sendAppLogs({
+                  appop,
+                  param: param ? JSON.stringify(param) : '{}'
+                }, asyncindx);
               }
-              window._yas.sendAppLogs({
-                appop,
-                param: param ? JSON.stringify(param) : '{}'
-              }, asyncindx);
-            }
-          }, 300);
-        });
+            }, 300);
+          });
+        } catch (e) {
+          // pass
+        }
       }
     }
   };
diff --git a/apps/utils/yas-constants.js b/apps/utils/yas-constants.js
new file mode 100644
index 0000000..aa72000
--- /dev/null
+++ b/apps/utils/yas-constants.js
@@ -0,0 +1,23 @@
+
+export default {
+  scene: {
+    index: 101,
+    list: 102,
+    author: 103,
+    authorList: 104,
+    topicList: 105,
+    newsDetail: 106
+  },
+  eventName: {
+    show: 'YB_SHOW_EVENT',
+    fav: 'YB_STROLL_ATC_LIKE_C',
+    star: 'YB_STROLL_ATC_COL_C',
+    avatar: 'YB_STROLL_ACT_AUTH_C',
+    fellow: 'YB_STROLL_AUTH_ATT_C',
+    articleExpand: 'YB_STROLL_LIST_ACT_C',
+    comment: 'YB_STROLL_ATC_COM_C',
+    productClick: 'YB_STROLL_ARC_RLT_PRD_C',
+    productFav: 'YB_STROLL_ARC_RLT_PRD_COL_C',
+    labelClick: 'YB_STROLL_ACT_LBL_C'
+  }
+};
diff --git a/doraemon/middleware/error-handler.js b/doraemon/middleware/error-handler.js
index c518a74..3ef77e9 100644
--- a/doraemon/middleware/error-handler.js
+++ b/doraemon/middleware/error-handler.js
@@ -1,19 +1,49 @@
+const _ = require('lodash');
 const logger = global.yoho.logger;
+const cache = global.yoho.cache.master;
+const helpers = global.yoho.helpers;
+
+const appName = 'h5'; // 与H5共用
+const LIMITER_IP_TIME = 3600; // 超出访问限制ip限制访问1小时
+
+const replaceKey = '__refer__';
+const checkRefer = helpers.urlFormat('/3party/check', {refer: replaceKey});
 
 /**
  * 服务器错误
  * @return {[type]}
  */
-exports.serverError = (err, req, res, next) => { // eslint-disable-line
+exports.serverError = (err = {}, req, res, next) => { // eslint-disable-line
   logger.error(`error at path: ${req.url}`);
   logger.error(`${req.url},${typeof err === 'object' ? JSON.stringify(err) : err}`);
 
+  if (err.apiRisk) { // 接口风控
+    let remoteIp = req.yoho.clientIp;
+
+    if (_.get(req.app.locals, 'wap.open.apmrisk', false)) {
+      cache.setAsync(`${appName}:limit2:${remoteIp}`, 1, LIMITER_IP_TIME);
+    } else {
+      cache.setAsync(`${appName}:limiter:${remoteIp}`, 1, LIMITER_IP_TIME);
+    }
+
+    req.session.apiRiskValidate = true;
+
+    if (req.xhr) {
+      return res.status(510).json({
+        code: err.code,
+        data: {refer: checkRefer.replace(replaceKey, req.get('Referer') || '')}
+      });
+    }
+
+    return res.redirect(checkRefer.replace(replaceKey, req.protocol + '://' + req.get('host') + req.originalUrl));
+  }
+
   res.status(err.code || 500);
 
   if (req.xhr) {
     return res.json({
-      code: 500,
-      message: '服务器错误!'
+      code: err.code || 500,
+      message: err.message || '服务器错误'
     });
   }
 
diff --git a/doraemon/middleware/ssr-api.js b/doraemon/middleware/ssr-api.js
index 4e1af97..e39589d 100644
--- a/doraemon/middleware/ssr-api.js
+++ b/doraemon/middleware/ssr-api.js
@@ -3,6 +3,7 @@ const ufoAPI = global.yoho.UfoAPI;
 const logger = global.yoho.logger;
 const checkParams = require('../../utils/check-params');
 const apiMaps = require('../../config/api-map');
+const errorHandler = require('./error-handler');
 
 module.exports = async(req, res, next) => {
   res.set({
@@ -76,10 +77,6 @@ module.exports = async(req, res, next) => {
       code: 400
     });
   } catch (error) {
-    logger.error(error);
-    return res.json({
-      code: error.code || 500,
-      message: error.message || '服务器错误'
-    });
+    return errorHandler.serverError(error, req, res, next);
   }
 };