前情提要:
muffet 第四堂課


第四堂課筆記

  1. tagtoo feed - 就是把資料庫的資料輸出成各種渠道的格式

  2. 依照目前的各種框架,我們會把廣告渠道分成兩個 repodashboard apiapi

  3. 只要是 GMC 所使用的 feed,就是放在 dashboard api,其他渠道全部都放在 api。

  4. 一般來說,tagtoo feed 是一個網址的形式,這個網址的內容我們會在後台設定,通常廣告會主動向我們拿資料,不過這時候就會發生,我們受限於廣告更新的速度 (GMC 一天只會向我們拿一次資料),後來 GMC 才提供 content API 的服務,我們才可以主動地把商品資料打給 GMC。簡單來講,傳統的 GMC,我們是被動的更新商品時間(一天一次),不過新的 GMC content api,我們可以主動提供給GMC,讓他更新商品的頻率變快 (我們自己可以決定什麼時間點要打一次 api 給 GMC)。

  5. 還有提供一個 FTP protocol 的檔案伺服器,他放在 cron-jobs 這個 repo 裡面,他的用意是,像是 line、或是其他以後可能會新增的渠道,他所接受的通訊協定、他的資料格式,是特定的,line 的格式只接受 FTP 格式,而且只接受 CSV 檔案,所以後來多做了一個 FTP SERVER,還多做了一個 cron-jobs 的服務,也就是因為他接受的格式是 CSV 檔案,所以我們會定期產 CSV 檔案,並放在 FTP server 上,line 就會跟 FTP SERVER 溝通,並且 line 就會抓到某一家客戶的 CSV 檔,

dashboard-api

  1. dashboard-api 的格式是這樣 - https://dashboard-api.tagtoo.com.tw/api/feed/merchantCenter?advertiser_id=EC_ID,呼叫時只要改變最後面的 ec_id 就好。

  2. Google Merchant Center 後台設定,這個 op 會設定好 => OP 會完成:在「產品」>「動態饋給」>「主要動態饋給」中開設,並填入 Tagtoo Feed 網址。


只要我們 muffet 這邊設定好,商品資料有存到資料庫裡面,這個 endpoint 就會根據他所收到的 ec_id 去資料庫抓到這一家 ec 的商品資料,並且輸出成 GMC 所需要的商品格式


muffet 怎麼把資料送到資料庫

  1. muffet 會送一段 product data 的 queryString 到後台的 server,那台 server (被稱作 track view),他的 repo 就叫 track view,那台 server 在做的事情就是,會去 validate 從 muffet 送過來的資料,都通過的話,那台 server 會再送一個 request 到 dashboard-api。
  2. dashboard api 這邊專門接收外界要對 DB 存資料的一段,對外的 interface 就在這邊,這一段就是前段搜集資料,最後丟到 db 處理資料的地方。

dashboard-api 本地開發

  1. api 本地開發我們會直接連到 db 的資料,這樣會比較快
  2. 如何在本機啟 server,可以從 CI/CD 流程去判斷,在 CI/CD 過程中,首先我們會 build image,然後我們會丟到 google cloud container Registry 上面,這個上面會有一個 production 環境下的 image,只要把這個東西拉下來就好,把他拉下來之後,再針對 local 做一些變動,接著再用 docker compose,用 docker run 也可以,總之就是把 image 拉下來之後,就可以在 local 跑,我們可以隨時改判斷,看 api 的變化。
  3. 記得要連到 production 環境下的 DB,這個部分我們要去修改 Django database 的 setting,現在在我們的 dashboard-api repo 裡面,裡面就有寫到 cloud SQL 的一些設定。

Ps. 還有用到 manage.run server 那個指令,不過用這個指令會有 dependency 的問題,所以不建議。

api

  1. api 的格式是這樣:​​https://api.tagtoo.com.tw//feed/[/special]/

  2. API 服務會提供其他所有廣告渠道,他的網址 path 會比較複雜一點,有 versionCHANNEL_NAME 還有要不要加上 special ,最後再加上 ec_id

  3. 目前只有 facebook 這個渠道有設定到 3 個版本,什麼時候會用到 v1 / v2 / v3 ?

v1

v1 就是一個最基本的 DPA XML 檔案

class Facebook(FeedHandler, XmlHandler):
    """
    XML feed for Facebook Dynamic Product Ads.
    """
    publisher_id = 71
    template = 'feed/facebook_feed.xml'

    def get(self, advertiser_id):
        logging.info(advertiser_id)
        advertiser, products = self.get_advertiser_and_products(advertiser_id)
        if not advertiser or advertiser_id == '1186':
            return self.return_404()

        self.format_to_xml(products)
        return self.items_to_xml(products, advertiser)

v2

v2 是我們提供乾淨的商品網址,因為從這個網址出來的東西,會帶有塔圖的轉址,這個轉址會讓使用者點擊的這個 feed 裡面商品的時候,可以讓我們幫商品帶上一些想要增加的參數 Ps. 這個轉址也是同樣一台的 server

class FacebookV2(Facebook):
    """
    XML feed with original link for Facebook Dynamic Product Ads.
    """
    template = 'feed/facebook_feed_v2.xml'

假設今天客戶想要幫商品增加 追蹤參數,OP 會直接在後台幫他們加上追蹤參數
Ps. 有時候會要我們幫他們增加,如果需要我們增加,就要跟他們確定現在是使用哪一個版本

v3

如果今天有子類商品,就要用這個版本:

class FacebookV3(Facebook):
    """
    XML feed with variants extension for Facebok Dynamic Product Ads.
    """
    template = 'feed/facebook_feed.xml'

    def get(self, advertiser_id):
        logging.info(advertiser_id)
        advertiser, products = self.get_advertiser_and_products(advertiser_id)
        if not advertiser or advertiser_id == '1186':
            return self.return_404()
        else:
            products = extend_product_variants(products)

        self.format_to_xml(products)
        return self.items_to_xml(products, advertiser)

Ps. 通常在設定 muffet 的時候,就會跟 OP 溝通要不要抓子類商品,所以正常的情況下,這家新客 OP 沒有跟你講要抓子類商品(ex. 一件衣服有很多顏色、尺寸之類的)。

special 是啥

special 的邏輯是,我們在產 feed 的時候,如果有一些特別的判斷邏輯,程式會做另外設定,有些 OP 在投廣告的時候會有一些很特別的需求,但是我們又不想干擾到原本渠道的設定,所以我們會跟他說我們產一個新的路徑給你,這個路徑就是會有 OP 想要投廣告的特別資料。

所以基本上,網址上有 special 的時候,我們就有 special feed 的做法,比如說像 orbis 這一家,他們的各個渠道都會加上這個 path_name,是因為他們有自己的追蹤碼,想要去做自己的追蹤,但是我們不想讓他污染到我們原先 muffet 抓的 feed 的資料,所以就使用 special_path。 -> 這個 PR 要找一下,不確定是哪一個。

簡單說就是,提供客戶一個客製化的商品資料內容。

Ps. FB 的後台設定(就是 howard 第四堂課貼的那張圖),記得要設定成 取代/排成,這個好處是,如果這一次的商品資料更新中,沒有某一個商品的話,那原先在線上的那個商品,就會被拿掉,也就是說這個好處是不會有過期/不需要的商品在上面

api 一些路徑說明

像下面這個路徑為什麼有一段的原因:

# api/index.py
import webapp2
app = webapp2.WSGIApplication([
  # ...
    (r'/feed/special/NBr3I5Kqe8YNFhp7o68RK4LkIoccirJl', 'apps.feed.views.JollyBuyFacebook'),
    (r'/feed/special/rYSBpTJbIA4X5P9WnmXGhBAHYTPVLRKk', 'apps.feed.views.JollyBuyInstagram'),
  # ... 
])    

像 JollyBuy 這家客戶,他們當時有另外一家代理商,也是使用塔圖的 feed,但是他們會從我們 feed 裡面的 ec_id,去猜其他家客戶,所以後來就給一串亂碼給客戶。


query string 和 path_name 都是用來客製化 feed 的,所以我們的網址,不管是 dashboard-api 還是 api,當有客製化需求的時候,我們一定是透過 path_name 或是 query string, 來告訴我們的產 feed 流程要做哪些相對應的變化,基本上 path_name 就是有沒有 special 的差別,但是後面的 query string 就有很多的差異
只要外部有帶上其他的 query string ,並且 code 的邏輯也有針對 query string 做特別的處理,我們就可以抓出特別的商品資料


cron jobs 在幹嘛

cron jobs 會去做的事情就是,他會去跟 api 拿商品資料回來,如果今天客戶的 CSV檔(商品資料)想要特別的東西,我們就是透過多開一個 query string 的方式,來告訴 API 我要特別的東西。
之前有加過一個 constant tracking 的東西,就是客戶自己有想要的追蹤碼,但是他的追蹤碼只有 line 的渠道想要做,所以我們可以就加在 cron job 下面,line 的這個東西。

content API 在幹嘛

  1. 這個連結是 content API 的 action 介紹: https://github.com/Tagtoo/api/blob/529a4cd7281e84fba78d424a2349563fc0b91274/apps/Merchant_center/views.py,也就是 daily_update、hourly_update 之類的設定。

  2. content API 有另外一套流程, https://github.com/Tagtoo/api/tree/529a4cd7281e84fba78d424a2349563fc0b91274/apps/Merchant_center#readme 這一份是當初寫的 readme。

這一整個流程,都是當初我們對客戶的 GMC (不管是我們開的還是客戶開的),我們都會有一些特定的設定方法,目前是用 google sheet 去做操作,所以從這邊 https://github.com/Tagtoo/api/blob/529a4cd7281e84fba78d424a2349563fc0b91274/apps/Merchant_center/services.py 可以看出,我們可以針對不同的 ec_id ,做不同的 execute_ec_task,

Ps .GMC 我們目前大概設定四個時段,這四個時段我們會去主動更新 api