15

I'm trying to load some Responsive ads in an AdComponent in my app. The component is dead simple:

import { Component } from '@angular/core';
import { FORM_DIRECTIVES, CORE_DIRECTIVES } from '@angular/common';

@Component({
  selector: 'ad',
  templateUrl: 'app/views/ad.html',
  directives: [ FORM_DIRECTIVES, CORE_DIRECTIVES ]
})
export class AdComponent {}

ad.html:

<div class="demo-card-wide mdl-card mdl-shadow--2dp ad-card">
  <div class="mdl-card__supporting-text">
    <script async src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
    <ins class="adsbygoogle"
        style="display:block"
        data-ad-client="ca-pub-0123456789"
        data-ad-slot="0123456789"
        data-ad-format="rectangle, horizontal"></ins>
    <script>
    (adsbygoogle = window.adsbygoogle || []).push({});
    </script>
  </div>
</div>

I'm finding that these script tags don't make it into the UI and this seems to be a purposeful decision.

I might be able to move around some of the code such as the js reference into the head of my index.html and the window.adsbygoogle part into the component constructor but I'm not sure if these kinds of modifications are allowed or if there's a better alternative to get these ads to work in Angular 2.

Does anybody have any experience with Google's Adsense ads working in Angular 2? Is there a different, proper way to do this?

jaibatrik
  • 6,770
  • 9
  • 33
  • 62
Corey Ogburn
  • 24,072
  • 31
  • 113
  • 188

4 Answers4

17

This is working for me:

TopBannerComponent.ts ==>

    import {Component,OnInit,AfterViewInit} from '@angular/core'

    @Component({
      moduleId: module.id,
      selector: 'google-adsense',
      template: ` <div>
            <ins class="adsbygoogle"
                style="display:block"
                data-ad-client="ca-pub-XXXXXXXXXXXXXX"
                data-ad-slot="8184819393"
                data-ad-format="auto"></ins>
             </div>   
                <br>            
      `,
   
    })

    export class TopBannerComponent implements AfterViewInit {
  
      constructor() {    
      } 
  
      ngAfterViewInit() {
         setTimeout(()=>{
          try{
            (window['adsbygoogle'] = window['adsbygoogle'] || []).push({});
          }catch(e){
            console.error("error");
          }
        },2000);
     }     
    }

Add this in your html where you want your ad to appear

<google-adsense></google-adsense>

Add google adsense script in your main html file

 <script async src=//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js></script>
Maayan Hope
  • 1,482
  • 17
  • 32
  • This worked for me in Angular 4. Note: Remove the `setTimeout`, it's not necessary. Thank you Maayan! – codepleb Oct 14 '17 at 07:12
  • 1
    thanks for this, I have 2 ads in the same component so I needed to call twice like this; try{ (window['adsbygoogle'] = window['adsbygoogle'] || []).push({}); (window['adsbygoogle'] = window['adsbygoogle'] || []).push({}); } – Sam Salim Dec 02 '17 at 17:00
  • This worked for me in Angular 6. Thanks, ngAfterViewInit always saves some of my issues. – davecar21 Aug 28 '18 at 13:39
  • Works for me too in Angular 6. Thanks! (Also removed the setTimeout and works fine) – tmoore Nov 15 '18 at 18:46
  • 'google-adsense' is the selector of the component. Did you add this component (above) to a module? – Maayan Hope Feb 20 '20 at 14:01
12

Here's what I've come up with and have working. I admit it may be stretching the "don't modify our code" rule of adsense, but I am doing my best to keep the heart of the code doing the same thing it's supposed to be doing:

// ad component
import { Component, AfterViewInit } from '@angular/core';
import { FORM_DIRECTIVES, CORE_DIRECTIVES } from '@angular/common';

@Component({
  selector: 'ad',
  templateUrl: 'app/views/ad.html',
  directives: [ FORM_DIRECTIVES, CORE_DIRECTIVES ]
})
export class AdComponent implements AfterViewInit {

  ngAfterViewInit() {
    try {
      (adsbygoogle = window.adsbygoogle || []).push({});
    } catch (e) {}
  }
}

// ad.html
<div class="demo-card-wide mdl-card mdl-shadow--2dp ad-card">
  <div class="mdl-card__supporting-text">
    <ins class="adsbygoogle" style="display:inline-block;width:330px;height:120px" data-ad-client="my_client_number" data-ad-slot="my_ad_slot_number"></ins>
  </div>
</div>

The design of my website has ads in Material Design Lite cards so that's the 2 outer divs in the view. The <ins> tag is cut and paste exactly the same tag adsense gave me.

I used AfterViewInit because it seems that adsense watches the array adsbygoogle to know when to scan for a new ad in the DOM. You don't want to modify this array until the DOM has the <ins> tag.

I wrapped the line in a try/catch because testing with an ad blocker showed that the component would throw an error when the blocker was turned on. In traditional pages the error would happen without side effects. In an Angular 2 page it stops the change detection.

I have done my best to keep with the spirit of what the adsense provided code is supposed to do and how it is intended to behave. My goal is to bring their out-of-date requirements into a functional Angular 2 application. This currently works just fine in Angular 2's RC4 across all browsers.

Here's hoping they don't see it as TOS break...

To get Typescript to agree with all this you'll need to add a few lines to a .d.ts file:

declare interface Window {
  adsbygoogle: any[];
}

declare var adsbygoogle: any[];

These will make Typescript accept the (adsbygoogle = window.adsbygoogle || []).push({}); line in the ad component.

Corey Ogburn
  • 24,072
  • 31
  • 113
  • 188
  • You'll have to add a definition to declare that it's there: `declare interface Window { adsbygoogle: any[]; }` – Corey Ogburn Aug 01 '16 at 21:01
  • Where should I declare this interface? – Cassio Landim Aug 01 '16 at 21:03
  • 1
    In my typings folder I have a folder named after my project that contains a `custom.d.ts`. I put it in there. – Corey Ogburn Aug 01 '16 at 21:07
  • I fixes the window.adsbygoogle compilation error but this still tries to assign a reference to a name that can't be found (`error TS2304: Cannot find name 'adsbygoogle'.`) – Cassio Landim Aug 01 '16 at 21:21
  • 1
    I just double checked my custom.d.ts, I have `adsbygoogle` declared twice. Once just like I said above in the Window interface, and a second time just as a var: `declare var adsbygoogle: any[];` – Corey Ogburn Aug 01 '16 at 21:23
  • Now it compiles! It throws an exception that is getting consumed by the try-catch even with adblock disabled. I'll deploy and see how it behaves in production. Thanks! – Cassio Landim Aug 01 '16 at 21:31
  • How does it works with responsive ads? if there is no width nor weight, I see nothing – TheUnreal Sep 03 '16 at 17:08
5

There is a module that works very well for me: ng2-adsense.

If you'll choose to use it, your HTML code will look something like this:

<ng2-adsense
  [adClient]="'ca-pub-7640562161899788'"
  [adSlot]="7259870550">
</ng2-adsense>

After you install the module, you need to import it and add it to your NgModule:

import { AdsenseModule } from 'ng2-adsense';
@NgModule({
  declarations: [AppComponent],
  imports: [
    BrowserModule,
    AdsenseModule, // <--- Add to imports
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

And add this standard adsense code in your index.html:

<script async src=//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js></script>
Nirgn
  • 1,879
  • 4
  • 23
  • 28
1

Based on the above solutions I have created a simple solution that can be easy to implement. This solution works with Angular Universal SSR (server side rendering)

In index.html add script provided from Adsense

  <script data-ad-client="ca-pub-xxxxxxxxx" async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>

In component.ts file,

ngAfterViewInit() {
 try {
   (window['adsbygoogle'] = window['adsbygoogle'] || []).push({});
   
   // If you have two ad on the page, then add this again.
   //(window['adsbygoogle'] = window['adsbygoogle'] || []).push({});


 } catch (e) {}
}

In .html file, place ad sense code whenever the ad needs to be displayed.

        <div  class="">
         <ins class="adsbygoogle"
            style="display:block"
            data-ad-client="ca-pub-xxxxxxxxx"
            data-ad-slot="zzzzzzzz"
            data-ad-format="auto"
            data-full-width-responsive="true"></ins>
        </div>

Update: If ad doesn't show up then, set timeout in component.ts file

    ngAfterViewInit() {
     setTimeout(()=>{
      try {
       (window['adsbygoogle'] = window['adsbygoogle'] || []).push({});
      } catch (e) {}
     },500);
    }

Note: Test your code on registered domain or subdomain. On localhost, the ad will not display.

Keyul
  • 729
  • 1
  • 8
  • 20