SDK:
https://github.com/googleapis/google-api-php-client
OAuth
https://github.com/googleapis/google-api-php-client/blob/master/docs/oauth-web.md
Developer Console
Google Admin:
Child account:
.env
1 2 |
RECAPTCHA_SITE_KEY=xxxxx RECAPTCHA_SECRET=xxxxxx |
Front
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
<input type="hidden" id="grecaptcha" name="grecaptcha" value=""> <script src="https://www.google.com/recaptcha/api.js?render={{ env('RECAPTCHA_SITE_KEY') }}"></script> <script> $(document).ready(function(){ $('#submit').on('click', function(){ grecaptcha.ready(function() { grecaptcha.execute('{{ env('RECAPTCHA_SITE_KEY') }}', {action: 'submit'}).then(function(token) { $('#grecaptcha').val(token); $('#iform').submit(); }); }); }); }); </script> |
Backend
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
public function login_save(Request $req){ $captcha_token = $req->input('grecaptcha'); if($captcha_token == false){ return $this->fail_response('reCaptcha Error'); }else{ $result = $this->verify_recaptcha($captcha_token); if($result == false){ return $this->fail_response($this->err); } } //logg('ok'); } private function verify_recaptcha($response){ $recaptcha_url = 'https://www.google.com/recaptcha/api/siteverify'; $recaptcha_secret = env('RECAPTCHA_SECRET'); $recaptcha_response = $response; // Make and decode POST request: $recaptcha = file_get_contents($recaptcha_url . '?secret=' . $recaptcha_secret . '&response=' . $recaptcha_response); $recaptcha = json_decode($recaptcha); //logg($recaptcha); // Take action based on the score returned: if($recaptcha->success == false){ $errors = $recaptcha->{'error-codes'}; //logg($errors); $this->err = implode(', ', $errors); return false; }else{ if ($recaptcha->score >= 0.5) { // Verified - send email return true; } else { // Not verified - show form error $this->err = 'Score is too low'; return false; } } } |
Google Verify API response examples
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
Type: object<br/><pre>stdClass Object ( [success] => 1 [challenge_ts] => 2020-04-20T15:48:54Z [hostname] => localhost [score] => 0.9 [action] => signup ) </pre> Type: object<br/><pre>stdClass Object ( [success] => [error-codes] => Array ( [0] => timeout-or-duplicate ) ) </pre> |
Reference:
https://support.google.com/google-ads/answer/3103357?hl=zh-Hant
https://support.google.com/google-ads/answer/7305793
https://support.google.com/google-ads/answer/7540515?hl=zh-Hant
1 2 3 4 5 6 7 8 9 |
<!-- Global site tag (gtag.js) - AdWords: 0000000 --> <script async src="https://www.googletagmanager.com/gtag/js?id=AW-0000000"></script> <script> window.dataLayer = window.dataLayer || []; function gtag(){dataLayer.push(arguments);} gtag('js', new Date()); gtag('config', 'AW-0000000'); </script> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
<script> gtag('event', 'page_view', { 'send_to': 'AW-0000000', //零售 'ecomm_pagetype': 'replace with value',//recommended 'ecomm_prodid': 'replace with value',//required 'ecomm_totalvalue': 'replace with value',//recommended //Hotel 'hrental_enddate': 'replace with value', 'hrental_id': 'replace with value',//required 'hrental_pagetype': 'replace with value',//recommended 'hrental_startdate': 'replace with value', 'hrental_totalvalue': 'replace with value',//recommended //本地優惠 'local_id': 'replace with value',//required 'local_pagetype': 'replace with value',//recommended 'local_totalvalue': 'replace with value',//recommended //旅行 'travel_destid': 'replace with value',//required 'travel_enddate': 'replace with value', 'travel_originid': 'replace with value', 'travel_pagetype': 'replace with value',//recommended 'travel_startdate': 'replace with value', 'travel_totalvalue': 'replace with value',//recommended 'user_id': 'replace with value' }); </script> |
https://support.google.com/tagmanager/answer/7582054?hl=en
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
<script> window.dataLayer = window.dataLayer || []; var products = []; <?php foreach($order_products as $key => $item): ?> products.push({ 'name': '<?=$item->name?>', 'id': '<?=$item->product_id?>', 'price': '<?=round($item->price, 0)?>', 'brand': 'WIIB', 'category': 'Health', 'quantity': <?=$item->quantity?>, 'coupon': '' }); <?php endforeach; ?> dataLayer.push({ 'ecommerce': { 'purchase': { 'actionField': { 'id': '<?=$order->transaction_id?>', // Transaction ID. Required for purchases and refunds. 'affiliation': 'WIIB', 'revenue': '<?=round($order->amount, 0)?>', // Total transaction value (incl. tax and shipping) 'tax':'<?=$order->amount*0.05?>', 'shipping': '<?=$order->shipping_fee?>' }, 'products': products } }, 'event': 'transactionComplete' }); </script> |
Reference:
1 |
window.google_tag_manager[{{Container ID}}].onHtmlSuccess({{HTML ID}}); |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
function(){ try{ var products = google_tag_manager[{{Container ID}}].dataLayer.get("ecommerce").purchase.products; var productIds = []; for(i = 0; i < products.length; i++){ productIds.push(products[i].id); } return productIds; }catch(e){ return 'undefined'; } } |
Reference
1 2 3 4 5 6 7 8 9 10 11 12 |
<?php // Transaction Data $trans = array('id'=>'1234', 'affiliation'=>'Acme Clothing', 'revenue'=>'11.99', 'shipping'=>'5', 'tax'=>'1.29'); // List of Items Purchased. $items = array( array('sku'=>'SDFSDF', 'name'=>'Shoes', 'category'=>'Footwear', 'price'=>'100', 'quantity'=>'1'), array('sku'=>'123DSW', 'name'=>'Sandals', 'category'=>'Footwear', 'price'=>'87', 'quantity'=>'1'), array('sku'=>'UHDF93', 'name'=>'Socks', 'category'=>'Footwear', 'price'=>'5.99', 'quantity'=>'2') ); ?> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
<?php // Function to return the JavaScript representation of a TransactionData object. function getTransactionJs(&$trans) { return <<<HTML ga('ecommerce:addTransaction', { 'id': '{$trans['id']}', 'affiliation': '{$trans['affiliation']}', 'revenue': '{$trans['revenue']}', 'shipping': '{$trans['shipping']}', 'tax': '{$trans['tax']}' }); HTML; } // Function to return the JavaScript representation of an ItemData object. function getItemJs(&$transId, &$item) { return <<<HTML ga('ecommerce:addItem', { 'id': '$transId', 'name': '{$item['name']}', 'sku': '{$item['sku']}', 'category': '{$item['category']}', 'price': '{$item['price']}', 'quantity': '{$item['quantity']}' }); HTML; } ?> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
<!-- Begin HTML --> <script> ga('require', 'ecommerce'); <?php echo getTransactionJs($trans); foreach ($items as &$item) { echo getItemJs($trans['id'], $item); } ?> ga('ecommerce:send'); </script> |
Enhanced ecommerce tracking with tag manager
Reference:
Install Google Tag Manager in web
Create Tag for Pixel base code
Create Tags for Pixel built-in events
1 2 3 4 5 6 7 8 9 |
<script> fbq('track', 'AddToCart', { content_ids: {{Product SKU Array}}, content_type: 'product', content_name: {{Product Page - Product Name}}, value: {{Product Page - Product Price}}, currency: 'TWD' }); </script> |
1 2 3 4 5 6 7 8 9 10 |
<script> fbq('track', 'InitiateCheckout', { content_ids: {{Product SKU Array}}, content_type: 'product', content_name: {{Product Page - Product Name}}, value: {{Product Page - Product Price}}, currency: 'TWD', num_items: {{Product Item Number}} }); </script> |
Product Catalog for Pixel
Google Product Category and Product Type
Reference: